]> granicus.if.org Git - clang/commitdiff
Revert "Detect uses of mismatching forms of 'new' and 'delete'"
authorDiego Novillo <dnovillo@google.com>
Thu, 14 May 2015 20:57:48 +0000 (20:57 +0000)
committerDiego Novillo <dnovillo@google.com>
Thu, 14 May 2015 20:57:48 +0000 (20:57 +0000)
This reverts commit 742dc9b6c9686ab52860b7da39c3a126d8a97fbc.

This is generating multiple segfaults in our internal builds.
Test case coming up shortly.

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

17 files changed:
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/ExternalSemaSource.h
include/clang/Sema/MultiplexExternalSemaSource.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
include/clang/Serialization/ASTReader.h
lib/Sema/MultiplexExternalSemaSource.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaExprCXX.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp
test/Analysis/MismatchedDeallocator-checker-test.mm
test/Analysis/MismatchedDeallocator-path-notes.cpp
test/CodeGenCXX/new.cpp
test/SemaCXX/delete-mismatch.h [deleted file]
test/SemaCXX/delete.cpp

index 0df7f627bceb88b2b776a29afd01634669f80e08..b600ec1766e215ff156eaaa634731c002411a46f 100644 (file)
@@ -5510,12 +5510,7 @@ def err_delete_explicit_conversion : Error<
   "conversion function">;
 def note_delete_conversion : Note<"conversion to pointer type %0">;
 def warn_delete_array_type : Warning<
-  "'delete' applied to a pointer-to-array type %0 treated as 'delete[]'">;
-def warn_mismatched_delete_new : Warning<
-  "'delete%select{|[]}0' applied to a pointer that was allocated with "
-  "'new%select{[]|}0'; did you mean 'delete%select{[]|}0'?">,
-  InGroup<DiagGroup<"mismatched-new-delete">>;
-def note_allocated_here : Note<"allocated with 'new%select{[]|}0' here">;
+  "'delete' applied to a pointer-to-array type %0 treated as delete[]">;
 def err_no_suitable_delete_member_function_found : Error<
   "no suitable member %0 in %1">;
 def err_ambiguous_suitable_delete_member_function_found : Error<
index ef3d2dbff1421cfaba19f630cb8acf20a01f969d..de4672f1afd8c5e00644cb3fb6a60fca40134318 100644 (file)
@@ -27,7 +27,6 @@ template <class T, unsigned n> class SmallSetVector;
 namespace clang {
 
 class CXXConstructorDecl;
-class CXXDeleteExpr;
 class CXXRecordDecl;
 class DeclaratorDecl;
 class LookupResult;
@@ -80,9 +79,6 @@ public:
   virtual void ReadUndefinedButUsed(
                          llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined);
 
-  virtual void ReadMismatchingDeleteExpressions(llvm::MapVector<
-      FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &);
-
   /// \brief Do last resort, unqualified lookup on a LookupResult that
   /// Sema cannot find.
   ///
index af7083a82de7b72354b6eefedebeb15d6b634811..16646ba4adfaf3d547749b4085ff456a9b0de028 100644 (file)
@@ -230,10 +230,6 @@ public:
   void ReadUndefinedButUsed(
                 llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined) override;
 
-  void ReadMismatchingDeleteExpressions(llvm::MapVector<
-      FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
-                                            Exprs) override;
-
   /// \brief Do last resort, unqualified lookup on a LookupResult that
   /// Sema cannot find.
   ///
index cf7b316b0855f1576a66ec02347d006033d76b88..3bc1b4d7d36df4559cc4300b512dcc4fd81ea206 100644 (file)
@@ -78,7 +78,6 @@ namespace clang {
   typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
   class CXXConstructorDecl;
   class CXXConversionDecl;
-  class CXXDeleteExpr;
   class CXXDestructorDecl;
   class CXXFieldCollector;
   class CXXMemberCallExpr;
@@ -403,15 +402,6 @@ public:
   llvm::SmallSetVector<const TypedefNameDecl *, 4>
       UnusedLocalTypedefNameCandidates;
 
-  /// \brief Delete-expressions to be analyzed at the end of translation unit
-  ///
-  /// This list contains class members, and locations of delete-expressions
-  /// that could not be proven as to whether they mismatch with new-expression
-  /// used in initializer of the field.
-  typedef std::pair<SourceLocation, bool> DeleteExprLoc;
-  typedef llvm::SmallVector<DeleteExprLoc, 4> DeleteLocs;
-  llvm::MapVector<FieldDecl *, DeleteLocs> DeleteExprs;
-
   typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
 
   /// PureVirtualClassDiagSet - a set of class declarations which we have
@@ -896,11 +886,6 @@ public:
   void getUndefinedButUsed(
       SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
 
-  /// Retrieves list of suspicious delete-expressions that will be checked at
-  /// the end of translation unit.
-  const llvm::MapVector<FieldDecl *, DeleteLocs> &
-  getMismatchingDeleteExpressions() const;
-
   typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
   typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
 
@@ -8654,9 +8639,6 @@ private:
   /// attempts to add itself into the container
   void CheckObjCCircularContainer(ObjCMessageExpr *Message);
 
-  void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE);
-  void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
-                                 bool DeleteWasArrayForm);
 public:
   /// \brief Register a magic integral constant to be used as a type tag.
   void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
index e0f01c8a354530205cc95ec0d6462d17a260a9e8..511e73b96f9490ca7778d88f1dc685963277c497 100644 (file)
@@ -561,9 +561,6 @@ namespace clang {
       /// \brief Record code for the table of offsets to CXXCtorInitializers
       /// lists.
       CXX_CTOR_INITIALIZERS_OFFSETS = 53,
-
-      /// \brief Delete expressions that will be analyzed later.
-      DELETE_EXPRS_TO_ANALYZE = 54
     };
 
     /// \brief Record types used within a source manager block.
index 713f4c952a398edc2d1e9f79df60444d8de62d20..9f9b45e8a59efdac0b8798fda392938167f27ac4 100644 (file)
@@ -756,9 +756,6 @@ private:
   /// SourceLocation of a matching ODR-use.
   SmallVector<uint64_t, 8> UndefinedButUsed;
 
-  /// \brief Delete expressions to analyze at the end of translation unit.
-  SmallVector<uint64_t, 8> DelayedDeleteExprs;
-
   // \brief A list of late parsed template function data.
   SmallVector<uint64_t, 1> LateParsedTemplates;
 
@@ -1739,10 +1736,6 @@ public:
   void ReadUndefinedButUsed(
                llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) override;
 
-  void ReadMismatchingDeleteExpressions(llvm::MapVector<
-      FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
-                                            Exprs);
-
   void ReadTentativeDefinitions(
                             SmallVectorImpl<VarDecl *> &TentativeDefs) override;
 
index 9ecb5a7fefbc51934c4b8efd0cd376a7191f981e..51a12746fddaa03ee4d72aa591c9c7fde6ebc376 100644 (file)
@@ -212,15 +212,7 @@ void MultiplexExternalSemaSource::ReadUndefinedButUsed(
   for(size_t i = 0; i < Sources.size(); ++i)
     Sources[i]->ReadUndefinedButUsed(Undefined);
 }
-
-void MultiplexExternalSemaSource::ReadMismatchingDeleteExpressions(
-    llvm::MapVector<FieldDecl *,
-                    llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
-        Exprs) {
-  for (auto &Source : Sources)
-    Source->ReadMismatchingDeleteExpressions(Exprs);
-}
-
+  
 bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){ 
   for(size_t i = 0; i < Sources.size(); ++i)
     Sources[i]->LookupUnqualified(R, S);
index dea01bab079cb3fbd8196d38a576c8a844486737..6825dfa41fa481588e82cb051295b4f08ad71af3 100644 (file)
@@ -860,17 +860,6 @@ void Sema::ActOnEndOfTranslationUnit() {
     }
   }
 
-  if (!Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) {
-    if (ExternalSource)
-      ExternalSource->ReadMismatchingDeleteExpressions(DeleteExprs);
-    for (const auto &DeletedFieldInfo : DeleteExprs) {
-      for (const auto &DeleteExprLoc : DeletedFieldInfo.second) {
-        AnalyzeDeleteExprMismatch(DeletedFieldInfo.first, DeleteExprLoc.first,
-                                  DeleteExprLoc.second);
-      }
-    }
-  }
-
   // Check we've noticed that we're no longer parsing the initializer for every
   // variable. If we miss cases, then at best we have a performance issue and
   // at worst a rejects-valid bug.
@@ -1230,9 +1219,6 @@ void ExternalSemaSource::ReadUndefinedButUsed(
                        llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) {
 }
 
-void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
-    FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}
-
 void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
   SourceLocation Loc = this->Loc;
   if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
@@ -1481,8 +1467,3 @@ CapturedRegionScopeInfo *Sema::getCurCapturedRegion() {
 
   return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back());
 }
-
-const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> &
-Sema::getMismatchingDeleteExpressions() const {
-  return DeleteExprs;
-}
index 12f06360a1a457501c70136e4a54fea144719b75..b853eaefbe426c048e97d138962971a209476675 100644 (file)
@@ -2339,261 +2339,6 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
   return false;
 }
 
-namespace {
-/// \brief Checks whether delete-expression, and new-expression used for
-///  initializing deletee have the same array form.
-class MismatchingNewDeleteDetector {
-public:
-  enum MismatchResult {
-    /// Indicates that there is no mismatch or a mismatch cannot be proven.
-    NoMismatch,
-    /// Indicates that variable is initialized with mismatching form of \a new.
-    VarInitMismatches,
-    /// Indicates that member is initialized with mismatching form of \a new.
-    MemberInitMismatches,
-    /// Indicates that 1 or more constructors' definitions could not been
-    /// analyzed, and they will be checked again at the end of translation unit.
-    AnalyzeLater
-  };
-
-  /// \param EndOfTU True, if this is the final analysis at the end of
-  /// translation unit. False, if this is the initial analysis at the point
-  /// delete-expression was encountered.
-  explicit MismatchingNewDeleteDetector(bool EndOfTU)
-      : IsArrayForm(false), Field(nullptr), EndOfTU(EndOfTU),
-        HasUndefinedConstructors(false) {}
-
-  /// \brief Checks whether pointee of a delete-expression is initialized with
-  /// matching form of new-expression.
-  ///
-  /// If return value is \c VarInitMismatches or \c MemberInitMismatches at the
-  /// point where delete-expression is encountered, then a warning will be
-  /// issued immediately. If return value is \c AnalyzeLater at the point where
-  /// delete-expression is seen, then member will be analyzed at the end of
-  /// translation unit. \c AnalyzeLater is returned iff at least one constructor
-  /// couldn't be analyzed. If at least one constructor initializes the member
-  /// with matching type of new, the return value is \c NoMismatch.
-  MismatchResult analyzeDeleteExpr(const CXXDeleteExpr *DE);
-  /// \brief Analyzes a class member.
-  /// \param Field Class member to analyze.
-  /// \param DeleteWasArrayForm Array form-ness of the delete-expression used
-  /// for deleting the \p Field.
-  MismatchResult analyzeField(FieldDecl *Field, bool DeleteWasArrayForm);
-  /// List of mismatching new-expressions used for initialization of the pointee
-  llvm::SmallVector<const CXXNewExpr *, 4> NewExprs;
-  /// Indicates whether delete-expression was in array form.
-  bool IsArrayForm;
-  FieldDecl *Field;
-
-private:
-  const bool EndOfTU;
-  /// \brief Indicates that there is at least one constructor without body.
-  bool HasUndefinedConstructors;
-  /// \brief Returns \c CXXNewExpr from given initialization expression.
-  /// \param E Expression used for initializing pointee in delete-expression.
-  /// \param E can be a single-element \c InitListExpr consisting of
-  /// \param E new-expression.
-  const CXXNewExpr *getNewExprFromInitListOrExpr(const Expr *E);
-  /// \brief Returns whether member is initialized with mismatching form of
-  /// \c new either by the member initializer or in-class initialization.
-  ///
-  /// If bodies of all constructors are not visible at the end of translation
-  /// unit or at least one constructor initializes member with the matching
-  /// form of \c new, mismatch cannot be proven, and this function will return
-  /// \c NoMismatch.
-  MismatchResult analyzeMemberExpr(const MemberExpr *ME);
-  /// \brief Returns whether variable is initialized with mismatching form of
-  /// \c new.
-  ///
-  /// If variable is initialized with matching form of \c new or variable is not
-  /// initialized with a \c new expression, this function will return true.
-  /// If variable is initialized with mismatching form of \c new, returns false.
-  /// \param D Variable to analyze.
-  bool hasMatchingVarInit(const DeclRefExpr *D);
-  /// \brief Checks whether the constructor initializes pointee with mismatching
-  /// form of \c new.
-  ///
-  /// Returns true, if member is initialized with matching form of \c new in
-  /// member initializer list. Returns false, if member is initialized with the
-  /// matching form of \c new in this constructor's initializer or given
-  /// constructor isn't defined at the point where delete-expression is seen, or
-  /// member isn't initialized by the constructor.
-  bool hasMatchingNewInCtor(const CXXConstructorDecl *CD);
-  /// \brief Checks whether member is initialized with matching form of
-  /// \c new in member initializer list.
-  bool hasMatchingNewInCtorInit(const CXXCtorInitializer *CI);
-  /// Checks whether member is initialized with mismatching form of \c new by
-  /// in-class initializer.
-  MismatchResult analyzeInClassInitializer();
-};
-}
-
-MismatchingNewDeleteDetector::MismatchResult
-MismatchingNewDeleteDetector::analyzeDeleteExpr(const CXXDeleteExpr *DE) {
-  NewExprs.clear();
-  assert(DE && "Expected delete-expression");
-  IsArrayForm = DE->isArrayForm();
-  const Expr *E = DE->getArgument()->IgnoreParenImpCasts();
-  if (const MemberExpr *ME = dyn_cast<const MemberExpr>(E)) {
-    return analyzeMemberExpr(ME);
-  } else if (const DeclRefExpr *D = dyn_cast<const DeclRefExpr>(E)) {
-    if (!hasMatchingVarInit(D))
-      return VarInitMismatches;
-  }
-  return NoMismatch;
-}
-
-const CXXNewExpr *
-MismatchingNewDeleteDetector::getNewExprFromInitListOrExpr(const Expr *E) {
-  assert(E != nullptr && "Expected a valid initializer expression");
-  E = E->IgnoreParenImpCasts();
-  if (const InitListExpr *ILE = dyn_cast<const InitListExpr>(E)) {
-    if (ILE->getNumInits() == 1)
-      E = dyn_cast<const CXXNewExpr>(ILE->getInit(0)->IgnoreParenImpCasts());
-  }
-
-  return dyn_cast<const CXXNewExpr>(E);
-}
-
-bool MismatchingNewDeleteDetector::hasMatchingNewInCtorInit(
-    const CXXCtorInitializer *CI) {
-  const CXXNewExpr *NE = nullptr;
-  if (Field == CI->getMember() &&
-      (NE = getNewExprFromInitListOrExpr(CI->getInit()))) {
-    if (NE->isArray() == IsArrayForm)
-      return true;
-    else
-      NewExprs.push_back(NE);
-  }
-  return false;
-}
-
-bool MismatchingNewDeleteDetector::hasMatchingNewInCtor(
-    const CXXConstructorDecl *CD) {
-  if (CD->isImplicit())
-    return false;
-  const FunctionDecl *Definition = CD;
-  if (!CD->isThisDeclarationADefinition() && !CD->isDefined(Definition)) {
-    HasUndefinedConstructors = true;
-    return EndOfTU;
-  }
-  for (const auto *CI : cast<const CXXConstructorDecl>(Definition)->inits()) {
-    if (hasMatchingNewInCtorInit(CI))
-      return true;
-  }
-  return false;
-}
-
-MismatchingNewDeleteDetector::MismatchResult
-MismatchingNewDeleteDetector::analyzeInClassInitializer() {
-  assert(Field != nullptr && "This should be called only for members");
-  if (const CXXNewExpr *NE =
-          getNewExprFromInitListOrExpr(Field->getInClassInitializer())) {
-    if (NE->isArray() != IsArrayForm) {
-      NewExprs.push_back(NE);
-      return MemberInitMismatches;
-    }
-  }
-  return NoMismatch;
-}
-
-MismatchingNewDeleteDetector::MismatchResult
-MismatchingNewDeleteDetector::analyzeField(FieldDecl *Field,
-                                           bool DeleteWasArrayForm) {
-  assert(Field != nullptr && "Analysis requires a valid class member.");
-  this->Field = Field;
-  IsArrayForm = DeleteWasArrayForm;
-  const CXXRecordDecl *RD = cast<const CXXRecordDecl>(Field->getParent());
-  for (const auto *CD : RD->ctors()) {
-    if (hasMatchingNewInCtor(CD))
-      return NoMismatch;
-  }
-  if (HasUndefinedConstructors)
-    return EndOfTU ? NoMismatch : AnalyzeLater;
-  if (!NewExprs.empty())
-    return MemberInitMismatches;
-  return Field->hasInClassInitializer() ? analyzeInClassInitializer()
-                                        : NoMismatch;
-}
-
-MismatchingNewDeleteDetector::MismatchResult
-MismatchingNewDeleteDetector::analyzeMemberExpr(const MemberExpr *ME) {
-  assert(ME != nullptr && "Expected a member expression");
-  if (FieldDecl *F = dyn_cast<FieldDecl>(ME->getMemberDecl()))
-    return analyzeField(F, IsArrayForm);
-  return NoMismatch;
-}
-
-bool MismatchingNewDeleteDetector::hasMatchingVarInit(const DeclRefExpr *D) {
-  const CXXNewExpr *NE = nullptr;
-  if (const VarDecl *VD = dyn_cast<const VarDecl>(D->getDecl())) {
-    if (VD->hasInit() && (NE = getNewExprFromInitListOrExpr(VD->getInit())) &&
-        NE->isArray() != IsArrayForm) {
-      NewExprs.push_back(NE);
-    }
-  }
-  return NewExprs.empty();
-}
-
-static void
-DiagnoseMismatchedNewDelete(Sema &SemaRef, SourceLocation DeleteLoc,
-                            const MismatchingNewDeleteDetector &Detector) {
-  SourceLocation EndOfDelete = SemaRef.getLocForEndOfToken(DeleteLoc);
-  FixItHint H;
-  if (!Detector.IsArrayForm)
-    H = FixItHint::CreateInsertion(EndOfDelete, "[]");
-  else {
-    SourceLocation RSquare = Lexer::findLocationAfterToken(
-        DeleteLoc, tok::l_square, SemaRef.getSourceManager(),
-        SemaRef.getLangOpts(), true);
-    if (RSquare.isValid())
-      H = FixItHint::CreateRemoval(SourceRange(EndOfDelete, RSquare));
-  }
-  SemaRef.Diag(DeleteLoc, diag::warn_mismatched_delete_new)
-      << Detector.IsArrayForm << H;
-
-  for (const auto *NE : Detector.NewExprs)
-    SemaRef.Diag(NE->getExprLoc(), diag::note_allocated_here)
-        << Detector.IsArrayForm;
-}
-
-void Sema::AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE) {
-  if (Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation()))
-    return;
-  MismatchingNewDeleteDetector Detector(/*EndOfTU=*/false);
-  switch (Detector.analyzeDeleteExpr(DE)) {
-  case MismatchingNewDeleteDetector::VarInitMismatches:
-  case MismatchingNewDeleteDetector::MemberInitMismatches: {
-    DiagnoseMismatchedNewDelete(*this, DE->getLocStart(), Detector);
-    break;
-  }
-  case MismatchingNewDeleteDetector::AnalyzeLater: {
-    DeleteExprs[Detector.Field].push_back(
-        std::make_pair(DE->getLocStart(), DE->isArrayForm()));
-    break;
-  }
-  case MismatchingNewDeleteDetector::NoMismatch:
-    break;
-  }
-}
-
-void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
-                                     bool DeleteWasArrayForm) {
-  MismatchingNewDeleteDetector Detector(/*EndOfTU=*/true);
-  switch (Detector.analyzeField(Field, DeleteWasArrayForm)) {
-  case MismatchingNewDeleteDetector::VarInitMismatches:
-    llvm_unreachable("This analysis should have been done for class members.");
-  case MismatchingNewDeleteDetector::AnalyzeLater:
-    llvm_unreachable("Analysis cannot be postponed any point beyond end of "
-                     "translation unit.");
-  case MismatchingNewDeleteDetector::MemberInitMismatches:
-    DiagnoseMismatchedNewDelete(*this, DeleteLoc, Detector);
-    break;
-  case MismatchingNewDeleteDetector::NoMismatch:
-    break;
-  }
-}
-
 /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
 /// @code ::delete ptr; @endcode
 /// or
@@ -2709,6 +2454,12 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
       }
     }
 
+    // C++ [expr.delete]p2:
+    //   [Note: a pointer to a const type can be the operand of a
+    //   delete-expression; it is not necessary to cast away the constness
+    //   (5.2.11) of the pointer expression before it is used as the operand
+    //   of the delete-expression. ]
+
     if (Pointee->isArrayType() && !ArrayForm) {
       Diag(StartLoc, diag::warn_delete_array_type)
           << Type << Ex.get()->getSourceRange()
@@ -2783,7 +2534,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
           DeleteName);
 
     MarkFunctionReferenced(StartLoc, OperatorDelete);
-
+    
     // Check access and ambiguity of operator delete and destructor.
     if (PointeeRD) {
       if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
@@ -2793,11 +2544,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
     }
   }
 
-  CXXDeleteExpr *Result = new (Context) CXXDeleteExpr(
+  return new (Context) CXXDeleteExpr(
       Context.VoidTy, UseGlobal, ArrayForm, ArrayFormAsWritten,
       UsualArrayDeleteWantsSize, OperatorDelete, Ex.get(), StartLoc);
-  AnalyzeDeleteExprMismatch(Result);
-  return Result;
 }
 
 /// \brief Check the use of the given variable as a C++ condition in an if,
index 0aeb1fffabaaf73265b5474cd0f290f3e256814d..c4b4aec24a04858d3d0750ac2e62dc9f27dc26f7 100644 (file)
@@ -3021,18 +3021,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
             ReadSourceLocation(F, Record, I).getRawEncoding());
       }
       break;
-    case DELETE_EXPRS_TO_ANALYZE:
-      for (unsigned I = 0, N = Record.size(); I != N;) {
-        DelayedDeleteExprs.push_back(getGlobalDeclID(F, Record[I++]));
-        const uint64_t Count = Record[I++];
-        DelayedDeleteExprs.push_back(Count);
-        for (uint64_t C = 0; C < Count; ++C) {
-          DelayedDeleteExprs.push_back(ReadSourceLocation(F, Record, I).getRawEncoding());
-          bool IsArrayForm = Record[I++] == 1;
-          DelayedDeleteExprs.push_back(IsArrayForm);
-        }
-      }
-      break;
 
     case IMPORTED_MODULES: {
       if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) {
@@ -7025,21 +7013,6 @@ void ASTReader::ReadUndefinedButUsed(
   }
 }
 
-void ASTReader::ReadMismatchingDeleteExpressions(llvm::MapVector<
-    FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
-                                                     Exprs) {
-  for (unsigned Idx = 0, N = DelayedDeleteExprs.size(); Idx != N;) {
-    FieldDecl *FD = cast<FieldDecl>(GetDecl(DelayedDeleteExprs[Idx++]));
-    uint64_t Count = DelayedDeleteExprs[Idx++];
-    for (uint64_t C = 0; C < Count; ++C) {
-      SourceLocation DeleteLoc =
-          SourceLocation::getFromRawEncoding(DelayedDeleteExprs[Idx++]);
-      const bool IsArrayForm = DelayedDeleteExprs[Idx++];
-      Exprs[FD].push_back(std::make_pair(DeleteLoc, IsArrayForm));
-    }
-  }
-}
-
 void ASTReader::ReadTentativeDefinitions(
                   SmallVectorImpl<VarDecl *> &TentativeDefs) {
   for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
index c1398e26c7360d272eb03587b1491198b540254f..29a88a13d38a5cddd8f224108760e7315136c2a1 100644 (file)
@@ -4155,20 +4155,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
     AddSourceLocation(I->second, UndefinedButUsed);
   }
 
-  // Build a record containing all delete-expressions that we would like to
-  // analyze later in AST.
-  RecordData DeleteExprsToAnalyze;
-
-  for (const auto &DeleteExprsInfo :
-       SemaRef.getMismatchingDeleteExpressions()) {
-    AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze);
-    DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size());
-    for (const auto &DeleteLoc : DeleteExprsInfo.second) {
-      AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze);
-      DeleteExprsToAnalyze.push_back(DeleteLoc.second);
-    }
-  }
-
   // Write the control block
   WriteControlBlock(PP, Context, isysroot, OutputFile);
 
@@ -4438,10 +4424,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
   // Write the undefined internal functions and variables, and inline functions.
   if (!UndefinedButUsed.empty())
     Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed);
-
-  if (!DeleteExprsToAnalyze.empty())
-    Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze);
-
+  
   // Write the visible updates to DeclContexts.
   for (auto *DC : UpdatedDeclContexts)
     WriteDeclContextVisibleUpdate(DC);
index 6fab8bb668e836afe264a673b58b8f3169790218..fca02aa278fdd6f6756f96df8b15be44d101c875 100644 (file)
@@ -97,11 +97,9 @@ void testShouldReportDoubleFreeNotMismatched() {
   free(p);
   delete globalPtr; // expected-warning {{Attempt to free released memory}}
 }
-int *allocIntArray(unsigned c) {
-  return new int[c];
-}
+
 void testMismatchedChangePointeeThroughAssignment() {
-  int *arr = allocIntArray(4);
+  int *arr = new int[4];
   globalPtr = arr;
   delete arr; // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}}
-}
+}
\ No newline at end of file
index 3cc3e18c7c7ccbc254be812f584ef6a463977a15..15815e80bfa643e12dd0f8068fe74d9880bb42a0 100644 (file)
@@ -95,11 +95,8 @@ void testNew6() {
   realloc(p, sizeof(long)); // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not realloc()}}
 }
 
-int *allocInt() {
-  return new int;
-}
 void testNew7() {
-  int *p = allocInt();
+  int *p = new int;
   delete[] p; // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not 'delete[]'}}
 }
 
@@ -108,12 +105,8 @@ void testNew8() {
   delete[] p; // expected-warning{{Memory allocated by operator new should be deallocated by 'delete', not 'delete[]'}}
 }
 
-int *allocIntArray(unsigned c) {
-  return new int[c];
-}
-
 void testNew9() {
-  int *p = allocIntArray(1);
+  int *p = new int[1];
   delete p; // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}}
 }
 
index af24197f13e8f1f789b75e72668c1f070656efb3..686497c4a9c4856c5113fac74ca6c8cb9f8a50ac 100644 (file)
@@ -3,12 +3,9 @@
 // RUN: FileCheck --input-file=%t.plist %s
 
 void changePointee(int *p);
-int *allocIntArray(unsigned c) {
-  return new int[c]; // expected-note {{Memory is allocated}}
-}
 void test() {
-  int *p = allocIntArray(1); // expected-note {{Calling 'allocIntArray'}}
-  // expected-note@-1 {{Returned allocated memory}}
+  int *p = new int[1];
+  // expected-note@-1 {{Memory is allocated}}
   changePointee(p);
   delete p; // expected-warning {{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}}
   // expected-note@-1 {{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}}
@@ -27,124 +24,13 @@ void test() {
 // CHECK-NEXT:        <key>start</key>
 // CHECK-NEXT:         <array>
 // CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>10</integer>
-// CHECK-NEXT:           <key>col</key><integer>3</integer>
-// CHECK-NEXT:           <key>file</key><integer>0</integer>
-// CHECK-NEXT:          </dict>
-// CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>10</integer>
-// CHECK-NEXT:           <key>col</key><integer>5</integer>
-// CHECK-NEXT:           <key>file</key><integer>0</integer>
-// CHECK-NEXT:          </dict>
-// CHECK-NEXT:         </array>
-// CHECK-NEXT:        <key>end</key>
-// CHECK-NEXT:         <array>
-// CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>10</integer>
-// CHECK-NEXT:           <key>col</key><integer>12</integer>
-// CHECK-NEXT:           <key>file</key><integer>0</integer>
-// CHECK-NEXT:          </dict>
-// CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>10</integer>
-// CHECK-NEXT:           <key>col</key><integer>24</integer>
-// CHECK-NEXT:           <key>file</key><integer>0</integer>
-// CHECK-NEXT:          </dict>
-// CHECK-NEXT:         </array>
-// CHECK-NEXT:       </dict>
-// CHECK-NEXT:      </array>
-// CHECK-NEXT:    </dict>
-// CHECK-NEXT:    <dict>
-// CHECK-NEXT:     <key>kind</key><string>event</string>
-// CHECK-NEXT:     <key>location</key>
-// CHECK-NEXT:     <dict>
-// CHECK-NEXT:      <key>line</key><integer>10</integer>
-// CHECK-NEXT:      <key>col</key><integer>12</integer>
-// CHECK-NEXT:      <key>file</key><integer>0</integer>
-// CHECK-NEXT:     </dict>
-// CHECK-NEXT:     <key>ranges</key>
-// CHECK-NEXT:     <array>
-// CHECK-NEXT:       <array>
-// CHECK-NEXT:        <dict>
-// CHECK-NEXT:         <key>line</key><integer>10</integer>
-// CHECK-NEXT:         <key>col</key><integer>12</integer>
-// CHECK-NEXT:         <key>file</key><integer>0</integer>
-// CHECK-NEXT:        </dict>
-// CHECK-NEXT:        <dict>
-// CHECK-NEXT:         <key>line</key><integer>10</integer>
-// CHECK-NEXT:         <key>col</key><integer>27</integer>
-// CHECK-NEXT:         <key>file</key><integer>0</integer>
-// CHECK-NEXT:        </dict>
-// CHECK-NEXT:       </array>
-// CHECK-NEXT:     </array>
-// CHECK-NEXT:     <key>depth</key><integer>0</integer>
-// CHECK-NEXT:     <key>extended_message</key>
-// CHECK-NEXT:     <string>Calling &apos;allocIntArray&apos;</string>
-// CHECK-NEXT:     <key>message</key>
-// CHECK-NEXT:     <string>Calling &apos;allocIntArray&apos;</string>
-// CHECK-NEXT:    </dict>
-// CHECK-NEXT:    <dict>
-// CHECK-NEXT:     <key>kind</key><string>event</string>
-// CHECK-NEXT:     <key>location</key>
-// CHECK-NEXT:     <dict>
-// CHECK-NEXT:      <key>line</key><integer>6</integer>
-// CHECK-NEXT:      <key>col</key><integer>1</integer>
-// CHECK-NEXT:      <key>file</key><integer>0</integer>
-// CHECK-NEXT:     </dict>
-// CHECK-NEXT:     <key>depth</key><integer>1</integer>
-// CHECK-NEXT:     <key>extended_message</key>
-// CHECK-NEXT:     <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT:     <key>message</key>
-// CHECK-NEXT:     <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT:    </dict>
-// CHECK-NEXT:    <dict>
-// CHECK-NEXT:     <key>kind</key><string>control</string>
-// CHECK-NEXT:     <key>edges</key>
-// CHECK-NEXT:      <array>
-// CHECK-NEXT:       <dict>
-// CHECK-NEXT:        <key>start</key>
-// CHECK-NEXT:         <array>
-// CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>6</integer>
-// CHECK-NEXT:           <key>col</key><integer>1</integer>
-// CHECK-NEXT:           <key>file</key><integer>0</integer>
-// CHECK-NEXT:          </dict>
-// CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>6</integer>
-// CHECK-NEXT:           <key>col</key><integer>3</integer>
-// CHECK-NEXT:           <key>file</key><integer>0</integer>
-// CHECK-NEXT:          </dict>
-// CHECK-NEXT:         </array>
-// CHECK-NEXT:        <key>end</key>
-// CHECK-NEXT:         <array>
-// CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>7</integer>
-// CHECK-NEXT:           <key>col</key><integer>3</integer>
-// CHECK-NEXT:           <key>file</key><integer>0</integer>
-// CHECK-NEXT:          </dict>
-// CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>7</integer>
-// CHECK-NEXT:           <key>col</key><integer>8</integer>
-// CHECK-NEXT:           <key>file</key><integer>0</integer>
-// CHECK-NEXT:          </dict>
-// CHECK-NEXT:         </array>
-// CHECK-NEXT:       </dict>
-// CHECK-NEXT:      </array>
-// CHECK-NEXT:    </dict>
-// CHECK-NEXT:    <dict>
-// CHECK-NEXT:     <key>kind</key><string>control</string>
-// CHECK-NEXT:     <key>edges</key>
-// CHECK-NEXT:      <array>
-// CHECK-NEXT:       <dict>
-// CHECK-NEXT:        <key>start</key>
-// CHECK-NEXT:         <array>
-// CHECK-NEXT:          <dict>
 // CHECK-NEXT:           <key>line</key><integer>7</integer>
 // CHECK-NEXT:           <key>col</key><integer>3</integer>
 // CHECK-NEXT:           <key>file</key><integer>0</integer>
 // CHECK-NEXT:          </dict>
 // CHECK-NEXT:          <dict>
 // CHECK-NEXT:           <key>line</key><integer>7</integer>
-// CHECK-NEXT:           <key>col</key><integer>8</integer>
+// CHECK-NEXT:           <key>col</key><integer>5</integer>
 // CHECK-NEXT:           <key>file</key><integer>0</integer>
 // CHECK-NEXT:          </dict>
 // CHECK-NEXT:         </array>
@@ -152,12 +38,12 @@ void test() {
 // CHECK-NEXT:         <array>
 // CHECK-NEXT:          <dict>
 // CHECK-NEXT:           <key>line</key><integer>7</integer>
-// CHECK-NEXT:           <key>col</key><integer>10</integer>
+// CHECK-NEXT:           <key>col</key><integer>12</integer>
 // CHECK-NEXT:           <key>file</key><integer>0</integer>
 // CHECK-NEXT:          </dict>
 // CHECK-NEXT:          <dict>
 // CHECK-NEXT:           <key>line</key><integer>7</integer>
-// CHECK-NEXT:           <key>col</key><integer>12</integer>
+// CHECK-NEXT:           <key>col</key><integer>14</integer>
 // CHECK-NEXT:           <key>file</key><integer>0</integer>
 // CHECK-NEXT:          </dict>
 // CHECK-NEXT:         </array>
@@ -169,7 +55,7 @@ void test() {
 // CHECK-NEXT:     <key>location</key>
 // CHECK-NEXT:     <dict>
 // CHECK-NEXT:      <key>line</key><integer>7</integer>
-// CHECK-NEXT:      <key>col</key><integer>10</integer>
+// CHECK-NEXT:      <key>col</key><integer>12</integer>
 // CHECK-NEXT:      <key>file</key><integer>0</integer>
 // CHECK-NEXT:     </dict>
 // CHECK-NEXT:     <key>ranges</key>
@@ -177,52 +63,23 @@ void test() {
 // CHECK-NEXT:       <array>
 // CHECK-NEXT:        <dict>
 // CHECK-NEXT:         <key>line</key><integer>7</integer>
-// CHECK-NEXT:         <key>col</key><integer>10</integer>
+// CHECK-NEXT:         <key>col</key><integer>12</integer>
 // CHECK-NEXT:         <key>file</key><integer>0</integer>
 // CHECK-NEXT:        </dict>
 // CHECK-NEXT:        <dict>
 // CHECK-NEXT:         <key>line</key><integer>7</integer>
-// CHECK-NEXT:         <key>col</key><integer>19</integer>
+// CHECK-NEXT:         <key>col</key><integer>21</integer>
 // CHECK-NEXT:         <key>file</key><integer>0</integer>
 // CHECK-NEXT:        </dict>
 // CHECK-NEXT:       </array>
 // CHECK-NEXT:     </array>
-// CHECK-NEXT:     <key>depth</key><integer>1</integer>
+// CHECK-NEXT:     <key>depth</key><integer>0</integer>
 // CHECK-NEXT:     <key>extended_message</key>
 // CHECK-NEXT:     <string>Memory is allocated</string>
 // CHECK-NEXT:     <key>message</key>
 // CHECK-NEXT:     <string>Memory is allocated</string>
 // CHECK-NEXT:    </dict>
 // CHECK-NEXT:    <dict>
-// CHECK-NEXT:     <key>kind</key><string>event</string>
-// CHECK-NEXT:     <key>location</key>
-// CHECK-NEXT:     <dict>
-// CHECK-NEXT:      <key>line</key><integer>10</integer>
-// CHECK-NEXT:      <key>col</key><integer>12</integer>
-// CHECK-NEXT:      <key>file</key><integer>0</integer>
-// CHECK-NEXT:     </dict>
-// CHECK-NEXT:     <key>ranges</key>
-// CHECK-NEXT:     <array>
-// CHECK-NEXT:       <array>
-// CHECK-NEXT:        <dict>
-// CHECK-NEXT:         <key>line</key><integer>10</integer>
-// CHECK-NEXT:         <key>col</key><integer>12</integer>
-// CHECK-NEXT:         <key>file</key><integer>0</integer>
-// CHECK-NEXT:        </dict>
-// CHECK-NEXT:        <dict>
-// CHECK-NEXT:         <key>line</key><integer>10</integer>
-// CHECK-NEXT:         <key>col</key><integer>27</integer>
-// CHECK-NEXT:         <key>file</key><integer>0</integer>
-// CHECK-NEXT:        </dict>
-// CHECK-NEXT:       </array>
-// CHECK-NEXT:     </array>
-// CHECK-NEXT:     <key>depth</key><integer>0</integer>
-// CHECK-NEXT:     <key>extended_message</key>
-// CHECK-NEXT:     <string>Returned allocated memory</string>
-// CHECK-NEXT:     <key>message</key>
-// CHECK-NEXT:     <string>Returned allocated memory</string>
-// CHECK-NEXT:    </dict>
-// CHECK-NEXT:    <dict>
 // CHECK-NEXT:     <key>kind</key><string>control</string>
 // CHECK-NEXT:     <key>edges</key>
 // CHECK-NEXT:      <array>
@@ -230,25 +87,25 @@ void test() {
 // CHECK-NEXT:        <key>start</key>
 // CHECK-NEXT:         <array>
 // CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>10</integer>
+// CHECK-NEXT:           <key>line</key><integer>7</integer>
 // CHECK-NEXT:           <key>col</key><integer>12</integer>
 // CHECK-NEXT:           <key>file</key><integer>0</integer>
 // CHECK-NEXT:          </dict>
 // CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>10</integer>
-// CHECK-NEXT:           <key>col</key><integer>24</integer>
+// CHECK-NEXT:           <key>line</key><integer>7</integer>
+// CHECK-NEXT:           <key>col</key><integer>14</integer>
 // CHECK-NEXT:           <key>file</key><integer>0</integer>
 // CHECK-NEXT:          </dict>
 // CHECK-NEXT:         </array>
 // CHECK-NEXT:        <key>end</key>
 // CHECK-NEXT:         <array>
 // CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>13</integer>
+// CHECK-NEXT:           <key>line</key><integer>10</integer>
 // CHECK-NEXT:           <key>col</key><integer>3</integer>
 // CHECK-NEXT:           <key>file</key><integer>0</integer>
 // CHECK-NEXT:          </dict>
 // CHECK-NEXT:          <dict>
-// CHECK-NEXT:           <key>line</key><integer>13</integer>
+// CHECK-NEXT:           <key>line</key><integer>10</integer>
 // CHECK-NEXT:           <key>col</key><integer>8</integer>
 // CHECK-NEXT:           <key>file</key><integer>0</integer>
 // CHECK-NEXT:          </dict>
@@ -260,7 +117,7 @@ void test() {
 // CHECK-NEXT:     <key>kind</key><string>event</string>
 // CHECK-NEXT:     <key>location</key>
 // CHECK-NEXT:     <dict>
-// CHECK-NEXT:      <key>line</key><integer>13</integer>
+// CHECK-NEXT:      <key>line</key><integer>10</integer>
 // CHECK-NEXT:      <key>col</key><integer>3</integer>
 // CHECK-NEXT:      <key>file</key><integer>0</integer>
 // CHECK-NEXT:     </dict>
@@ -268,12 +125,12 @@ void test() {
 // CHECK-NEXT:     <array>
 // CHECK-NEXT:       <array>
 // CHECK-NEXT:        <dict>
-// CHECK-NEXT:         <key>line</key><integer>13</integer>
+// CHECK-NEXT:         <key>line</key><integer>10</integer>
 // CHECK-NEXT:         <key>col</key><integer>10</integer>
 // CHECK-NEXT:         <key>file</key><integer>0</integer>
 // CHECK-NEXT:        </dict>
 // CHECK-NEXT:        <dict>
-// CHECK-NEXT:         <key>line</key><integer>13</integer>
+// CHECK-NEXT:         <key>line</key><integer>10</integer>
 // CHECK-NEXT:         <key>col</key><integer>10</integer>
 // CHECK-NEXT:         <key>file</key><integer>0</integer>
 // CHECK-NEXT:        </dict>
@@ -295,7 +152,7 @@ void test() {
 // CHECK-NEXT:  <key>issue_hash</key><string>4</string>
 // CHECK-NEXT:  <key>location</key>
 // CHECK-NEXT:  <dict>
-// CHECK-NEXT:   <key>line</key><integer>13</integer>
+// CHECK-NEXT:   <key>line</key><integer>10</integer>
 // CHECK-NEXT:   <key>col</key><integer>3</integer>
 // CHECK-NEXT:   <key>file</key><integer>0</integer>
 // CHECK-NEXT:  </dict>
index c8e0acba7b05bbeb3f26ae85d4793256e150f4fb..59b899f26202f40cb3f3e46c0cc9fb3348e59969 100644 (file)
@@ -321,14 +321,14 @@ namespace N3664 {
   // CHECK-LABEL: define void @_ZN5N36641fEv
   void f() {
     // CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
-    int *p = new int; // expected-note {{allocated with 'new' here}}
+    int *p = new int;
     // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
     delete p;
 
     // CHECK: call noalias i8* @_Znam(i64 12) [[ATTR_BUILTIN_NEW]]
     int *q = new int[3];
     // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_BUILTIN_DELETE]]
-    delete[] p; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
+    delete [] p;
 
     // CHECK: call i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_BUILTIN_NOTHROW_NEW:#[^ ]*]]
     (void) new (nothrow) S[3];
diff --git a/test/SemaCXX/delete-mismatch.h b/test/SemaCXX/delete-mismatch.h
deleted file mode 100644 (file)
index 84fcd61..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Header for PCH test delete.cpp
-namespace pch_test {
-struct X {
-  int *a;
-  X();
-  X(int);
-  X(bool)
-    : a(new int[1]) { } // expected-note{{allocated with 'new[]' here}}
-  ~X()
-  {
-    delete a; // expected-warning{{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-    // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:9}:"[]"
-  }
-};
-}
index f808100a558c179fb0fe1e2a3f14d0524e607bd4..5824facc507b156a714d798ed5c1614c248791ed 100644 (file)
@@ -1,129 +1,9 @@
-// Test without PCH
-// RUN: %clang_cc1 -fsyntax-only -include %S/delete-mismatch.h -fdiagnostics-parseable-fixits -std=c++11 %s 2>&1 | FileCheck %s
-
-// Test with PCH
-// RUN: %clang_cc1 -x c++-header -std=c++11 -emit-pch -o %t %S/delete-mismatch.h
-// RUN: %clang_cc1 -std=c++11 -include-pch %t -DWITH_PCH -fsyntax-only -verify %s -ast-dump
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -fixit -x c++ %t
+// RUN: %clang_cc1 -E -o - %t | FileCheck %s
 
 void f(int a[10][20]) {
+  // CHECK: delete[] a;
   delete a; // expected-warning {{'delete' applied to a pointer-to-array type}}
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:9}:"[]"
-}
-namespace MemberCheck {
-struct S {
-  int *a = new int[5]; // expected-note4 {{allocated with 'new[]' here}}
-  int *b;
-  int *c;
-  static int *d;
-  S();
-  S(int);
-  ~S() {
-    delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-    delete b;   // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-    delete[] c; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
-  }
-  void f();
-};
-
-void S::f()
-{
-  delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-  delete b; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-}
-
-S::S()
-: b(new int[1]), c(new int) {} // expected-note3 {{allocated with 'new[]' here}}
-// expected-note@-1 {{allocated with 'new' here}}
-
-S::S(int i)
-: b(new int[i]), c(new int) {} // expected-note3 {{allocated with 'new[]' here}}
-// expected-note@-1 {{allocated with 'new' here}}
-
-struct S2 : S {
-  ~S2() {
-    delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-  }
-};
-int *S::d = new int[42]; // expected-note {{allocated with 'new[]' here}}
-void f(S *s) {
-  int *a = new int[1]; // expected-note {{allocated with 'new[]' here}}
-  delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-  delete s->a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-  delete s->b; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-  delete s->c;
-  delete s->d;
-  delete S::d; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-}
-
-// At least one constructor initializes field with matching form of 'new'.
-struct MatchingNewIsOK {
-  int *p;
-  bool is_array_;
-  MatchingNewIsOK() : p{new int}, is_array_(false) {}
-  explicit MatchingNewIsOK(unsigned c) : p{new int[c]}, is_array_(true) {}
-  ~MatchingNewIsOK() {
-    if (is_array_)
-      delete[] p;
-    else
-      delete p;
-  }
-};
-
-// At least one constructor's body is missing; no proof of mismatch.
-struct CantProve_MissingCtorDefinition {
-  int *p;
-  CantProve_MissingCtorDefinition();
-  CantProve_MissingCtorDefinition(int);
-  ~CantProve_MissingCtorDefinition();
-};
-
-CantProve_MissingCtorDefinition::CantProve_MissingCtorDefinition()
-  : p(new int)
-{ }
-
-CantProve_MissingCtorDefinition::~CantProve_MissingCtorDefinition()
-{
-  delete[] p;
-}
-
-struct base {};
-struct derived : base {};
-struct InitList {
-  base *p;
-  InitList() : p{new derived[1]} {}                     // expected-note {{allocated with 'new[]' here}}
-  explicit InitList(unsigned c) : p(new derived[c]) {}  // expected-note {{allocated with 'new[]' here}}
-  InitList(unsigned c, unsigned) : p{new derived[c]} {} // expected-note {{allocated with 'new[]' here}}
-  InitList(const char *) : p{new derived[1]} {}         // expected-note {{allocated with 'new[]' here}}
-  ~InitList() {
-    delete p; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-    delete [] p;
-  }
-};
-}
-
-namespace NonMemberCheck {
-#define DELETE_ARRAY(x) delete[] (x)
-#define DELETE(x) delete (x)
-void f() {
-  int *a = new int(5); // expected-note2 {{allocated with 'new' here}}
-  delete[] a;          // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
-  int *b = new int;
-  delete b;
-  int *c{new int};    // expected-note {{allocated with 'new' here}}
-  int *d{new int[1]}; // expected-note2 {{allocated with 'new[]' here}}
-  delete  [    ] c;   // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:17}:""
-  delete d;           // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:9}:"[]"
-  DELETE_ARRAY(a);    // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
-  DELETE(d);          // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
-}
 }
-#ifndef WITH_PCH
-pch_test::X::X()
-  : a(new int[1])  // expected-note{{allocated with 'new[]' here}}
-{ }
-pch_test::X::X(int i)
-  : a(new int[i])  // expected-note{{allocated with 'new[]' here}}
-{ }
-#endif