Optimize PartialDiagnostic's memory-allocation behavior by placing a
cache of PartialDiagnostic::Storage objects into an allocator within
the ASTContext. This eliminates a significant amount of malloc
traffic, for a 10% performance improvement in -fsyntax-only wall-clock
time with 403.gcc's combine.c.

Also, eliminate the RequireNonAbstractType hack I put in earlier,
which was but a symptom of this larger problem.

Fixes <rdar://problem/7806091>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99849 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 9e92855..cb6b76c 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -1017,6 +1017,8 @@
   DependentStoredDeclsMap *Map
     = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr);
 
+  // FIXME: Allocate the copy of the PartialDiagnostic via the ASTContext's
+  // BumpPtrAllocator, rather than the ASTContext itself.
   DependentDiagnostic *DD = new (C) DependentDiagnostic(PDiag);
 
   // TODO: Maybe we shouldn't reverse the order during insertion.
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 21a8aea..9b8bae3 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/PartialDiagnostic.h"
 
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Parse/ParseDiagnostic.h"
@@ -1246,3 +1247,13 @@
 ///  DiagnosticClient should be included in the number of diagnostics
 ///  reported by Diagnostic.
 bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; }
+
+PartialDiagnostic::StorageAllocator::StorageAllocator() {
+  for (unsigned I = 0; I != NumCached; ++I)
+    FreeList[I] = Cached + I;
+  NumFreeListEntries = NumCached;
+}
+
+PartialDiagnostic::StorageAllocator::~StorageAllocator() {
+  assert(NumFreeListEntries == NumCached && "A partial is on the lamb");
+}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 9c661ba..859e497 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -312,30 +312,33 @@
 
     bool isMemberAccess() const { return IsMember; }
 
-    AccessedEntity(MemberNonce _,
+    AccessedEntity(ASTContext &Context, 
+                   MemberNonce _,
                    CXXRecordDecl *NamingClass,
                    AccessSpecifier Access,
                    NamedDecl *Target)
       : Access(Access), IsMember(true), 
         Target(Target), NamingClass(NamingClass),
-        Diag(0) {
+        Diag(0, Context.getDiagAllocator()) {
     }
 
-    AccessedEntity(MemberNonce _,
+    AccessedEntity(ASTContext &Context, 
+                   MemberNonce _,
                    CXXRecordDecl *NamingClass,
                    DeclAccessPair FoundDecl)
       : Access(FoundDecl.getAccess()), IsMember(true), 
         Target(FoundDecl.getDecl()), NamingClass(NamingClass),
-        Diag(0) {
+        Diag(0, Context.getDiagAllocator()) {
     }
 
-    AccessedEntity(BaseNonce _,
+    AccessedEntity(ASTContext &Context, 
+                   BaseNonce _,
                    CXXRecordDecl *BaseClass,
                    CXXRecordDecl *DerivedClass,
                    AccessSpecifier Access)
       : Access(Access), IsMember(false),
         Target(BaseClass), NamingClass(DerivedClass),
-        Diag(0) {
+        Diag(0, Context.getDiagAllocator()) {
     }
 
     bool isQuiet() const { return Diag.getDiagID() == 0; }
@@ -363,7 +366,7 @@
     PartialDiagnostic &setDiag(unsigned DiagID) {
       assert(isQuiet() && "partial diagnostic already defined");
       assert(DiagID && "creating null diagnostic");
-      Diag = PartialDiagnostic(DiagID);
+      Diag.Reset(DiagID);
       return Diag;
     }
     const PartialDiagnostic &getDiag() const {
@@ -615,6 +618,11 @@
   /// \brief Emit a partial diagnostic.
   SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD);
 
+  /// \brief Build a partial diagnostic. 
+  PartialDiagnostic PDiag(unsigned DiagID = 0) {
+    return PartialDiagnostic(DiagID, Context.getDiagAllocator());
+  }
+  
   virtual void DeleteExpr(ExprTy *E);
   virtual void DeleteStmt(StmtTy *S);
 
@@ -732,10 +740,12 @@
 
   bool RequireCompleteType(SourceLocation Loc, QualType T,
                            const PartialDiagnostic &PD,
-                           std::pair<SourceLocation,
-                                     PartialDiagnostic> Note =
-                            std::make_pair(SourceLocation(), PDiag()));
-
+                           std::pair<SourceLocation, PartialDiagnostic> Note);
+  bool RequireCompleteType(SourceLocation Loc, QualType T,
+                           const PartialDiagnostic &PD);
+  bool RequireCompleteType(SourceLocation Loc, QualType T,
+                           unsigned DiagID);
+  
   QualType getQualifiedNameType(const CXXScopeSpec &SS, QualType T);
 
   QualType BuildTypeofExprType(Expr *E);
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 9ceb17c..e7ea204 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -768,14 +768,16 @@
   if (!TargetD) return;
 
   if (DD.isAccessToMember()) {
-    AccessedEntity Entity(AccessedEntity::Member,
+    AccessedEntity Entity(Context,
+                          AccessedEntity::Member,
                           cast<CXXRecordDecl>(NamingD),
                           Access,
                           cast<NamedDecl>(TargetD));
     Entity.setDiag(DD.getDiagnostic());
     CheckAccess(*this, Loc, Entity);
   } else {
-    AccessedEntity Entity(AccessedEntity::Base,
+    AccessedEntity Entity(Context,
+                          AccessedEntity::Base,
                           cast<CXXRecordDecl>(TargetD),
                           cast<CXXRecordDecl>(NamingD),
                           Access);
@@ -791,7 +793,8 @@
       Found.getAccess() == AS_public)
     return AR_accessible;
 
-  AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found);
+  AccessedEntity Entity(Context, AccessedEntity::Member, E->getNamingClass(), 
+                        Found);
   Entity.setDiag(diag::err_access) << E->getSourceRange();
 
   return CheckAccess(*this, E->getNameLoc(), Entity);
@@ -805,7 +808,8 @@
       Found.getAccess() == AS_public)
     return AR_accessible;
 
-  AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found);
+  AccessedEntity Entity(Context, AccessedEntity::Member, E->getNamingClass(), 
+                        Found);
   Entity.setDiag(diag::err_access) << E->getSourceRange();
 
   return CheckAccess(*this, E->getMemberLoc(), Entity);
@@ -823,7 +827,7 @@
     return AR_accessible;
 
   CXXRecordDecl *NamingClass = Dtor->getParent();
-  AccessedEntity Entity(AccessedEntity::Member, NamingClass,
+  AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass,
                         DeclAccessPair::make(Dtor, Access));
   Entity.setDiag(PDiag); // TODO: avoid copy
 
@@ -839,7 +843,7 @@
     return AR_accessible;
 
   CXXRecordDecl *NamingClass = Constructor->getParent();
-  AccessedEntity Entity(AccessedEntity::Member, NamingClass,
+  AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass,
                         DeclAccessPair::make(Constructor, Access));
   Entity.setDiag(diag::err_access_ctor);
 
@@ -857,7 +861,7 @@
     return AR_accessible;
 
   CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
-  AccessedEntity Entity(AccessedEntity::Member, NamingClass,
+  AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass,
                         DeclAccessPair::make(Target, Access));
   Entity.setDiag(Diag);
   return CheckAccess(*this, UseLoc, Entity);
@@ -874,7 +878,7 @@
       Found.getAccess() == AS_public)
     return AR_accessible;
 
-  AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found);
+  AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, Found);
   Entity.setDiag(diag::err_access)
     << PlacementRange;
 
@@ -895,7 +899,7 @@
   assert(RT && "found member operator but object expr not of record type");
   CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
 
-  AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found);
+  AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, Found);
   Entity.setDiag(diag::err_access)
     << ObjectExpr->getSourceRange()
     << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
@@ -929,7 +933,8 @@
   BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
   DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
 
-  AccessedEntity Entity(AccessedEntity::Base, BaseD, DerivedD, Path.Access);
+  AccessedEntity Entity(Context, AccessedEntity::Base, BaseD, DerivedD, 
+                        Path.Access);
   if (DiagID)
     Entity.setDiag(DiagID) << Derived << Base;
 
@@ -946,7 +951,7 @@
 
   for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
     if (I.getAccess() != AS_public) {
-      AccessedEntity Entity(AccessedEntity::Member,
+      AccessedEntity Entity(Context, AccessedEntity::Member,
                             R.getNamingClass(),
                             I.getPair());
       Entity.setDiag(diag::err_access);
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 285ee49..2b93d38 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -315,7 +315,7 @@
     assert(DestPointer && "Reference to void is not possible");
   } else if (DestRecord) {
     if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
-                                 PDiag(diag::err_bad_dynamic_cast_incomplete)
+                               Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
                                    << DestRange))
       return;
   } else {
@@ -353,7 +353,7 @@
   const RecordType *SrcRecord = SrcPointee->getAs<RecordType>();
   if (SrcRecord) {
     if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
-                                 PDiag(diag::err_bad_dynamic_cast_incomplete)
+                             Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
                                    << SrcExpr->getSourceRange()))
       return;
   } else {
@@ -698,8 +698,8 @@
                   QualType OrigDestType, unsigned &msg, 
                   CastExpr::CastKind &Kind) {
   // We can only work with complete types. But don't complain if it doesn't work
-  if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, PDiag(0)) ||
-      Self.RequireCompleteType(OpRange.getBegin(), DestType, PDiag(0)))
+  if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, Self.PDiag(0)) ||
+      Self.RequireCompleteType(OpRange.getBegin(), DestType, Self.PDiag(0)))
     return TC_NotApplicable;
 
   // Downcast can only happen in class hierarchies, so we need classes.
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a7671a2..efd34f9 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1865,7 +1865,7 @@
 
     CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context);
     CheckDestructorAccess(Field->getLocation(), Dtor,
-                          PartialDiagnostic(diag::err_access_dtor_field)
+                          PDiag(diag::err_access_dtor_field)
                             << Field->getDeclName()
                             << FieldType);
 
@@ -1893,7 +1893,7 @@
 
     // FIXME: caret should be on the start of the class name
     CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor,
-                          PartialDiagnostic(diag::err_access_dtor_base)
+                          PDiag(diag::err_access_dtor_base)
                             << Base->getType()
                             << Base->getSourceRange());
     
@@ -1918,7 +1918,7 @@
 
     CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
     CheckDestructorAccess(ClassDecl->getLocation(), Dtor,
-                          PartialDiagnostic(diag::err_access_dtor_vbase)
+                          PDiag(diag::err_access_dtor_vbase)
                             << VBase->getType());
 
     MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
@@ -1939,9 +1939,6 @@
 bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
                                   unsigned DiagID, AbstractDiagSelID SelID,
                                   const CXXRecordDecl *CurrentRD) {
-  if (!getLangOptions().CPlusPlus)
-    return false;
-
   if (SelID == -1)
     return RequireNonAbstractType(Loc, T,
                                   PDiag(DiagID), CurrentRD);
@@ -3851,7 +3848,7 @@
                                   BaseClassDecl)) {
       CheckDirectMemberAccess(Base->getSourceRange().getBegin(),
                               BaseAssignOpMethod,
-                              PartialDiagnostic(diag::err_access_assign_base)
+                              PDiag(diag::err_access_assign_base)
                                 << Base->getType());
 
       MarkDeclarationReferenced(CurrentLocation, BaseAssignOpMethod);
@@ -3870,7 +3867,7 @@
                                   FieldClassDecl)) {
         CheckDirectMemberAccess(Field->getLocation(),
                                 FieldAssignOpMethod,
-                                PartialDiagnostic(diag::err_access_assign_field)
+                                PDiag(diag::err_access_assign_field)
                                   << Field->getDeclName() << Field->getType());
 
         MarkDeclarationReferenced(CurrentLocation, FieldAssignOpMethod);
@@ -3952,7 +3949,7 @@
         BaseClassDecl->getCopyConstructor(Context, TypeQuals)) {
       CheckDirectMemberAccess(Base->getSourceRange().getBegin(),
                               BaseCopyCtor,
-                              PartialDiagnostic(diag::err_access_copy_base)
+                              PDiag(diag::err_access_copy_base)
                                 << Base->getType());
 
       MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
@@ -3971,7 +3968,7 @@
           FieldClassDecl->getCopyConstructor(Context, TypeQuals)) {
         CheckDirectMemberAccess(Field->getLocation(),
                                 FieldCopyCtor,
-                                PartialDiagnostic(diag::err_access_copy_field)
+                                PDiag(diag::err_access_copy_field)
                                   << Field->getDeclName() << Field->getType());
 
         MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
@@ -4066,7 +4063,7 @@
     CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context);
     MarkDeclarationReferenced(VD->getLocation(), Destructor);
     CheckDestructorAccess(VD->getLocation(), Destructor,
-                          PartialDiagnostic(diag::err_access_dtor_var)
+                          PDiag(diag::err_access_dtor_var)
                             << VD->getDeclName()
                             << VD->getType());
   }
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 5767551..eae30dc 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -98,8 +98,8 @@
 bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
   bool MissingExceptionSpecification = false;
   bool MissingEmptyExceptionSpecification = false;
-  if (!CheckEquivalentExceptionSpec(diag::err_mismatched_exception_spec,
-                                    diag::note_previous_declaration,
+  if (!CheckEquivalentExceptionSpec(PDiag(diag::err_mismatched_exception_spec),
+                                    PDiag(diag::note_previous_declaration),
                                     Old->getType()->getAs<FunctionProtoType>(),
                                     Old->getLocation(),
                                     New->getType()->getAs<FunctionProtoType>(),
@@ -234,8 +234,9 @@
 bool Sema::CheckEquivalentExceptionSpec(
     const FunctionProtoType *Old, SourceLocation OldLoc,
     const FunctionProtoType *New, SourceLocation NewLoc) {
-  return CheckEquivalentExceptionSpec(diag::err_mismatched_exception_spec,
-                                      diag::note_previous_declaration,
+  return CheckEquivalentExceptionSpec(
+                                    PDiag(diag::err_mismatched_exception_spec),
+                                      PDiag(diag::note_previous_declaration),
                                       Old, OldLoc, New, NewLoc);
 }
 
@@ -451,7 +452,8 @@
     const FunctionProtoType *Source, SourceLocation SourceLoc)
 {
   if (CheckSpecForTypesEquivalent(*this,
-                           PDiag(diag::err_deep_exception_specs_differ) << 0, 0,
+                           PDiag(diag::err_deep_exception_specs_differ) << 0, 
+                                  PDiag(),
                                   Target->getResultType(), TargetLoc,
                                   Source->getResultType(), SourceLoc))
     return true;
@@ -462,7 +464,8 @@
          "Functions have different argument counts.");
   for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) {
     if (CheckSpecForTypesEquivalent(*this,
-                           PDiag(diag::err_deep_exception_specs_differ) << 1, 0,
+                           PDiag(diag::err_deep_exception_specs_differ) << 1, 
+                                    PDiag(),
                                     Target->getArgType(i), TargetLoc,
                                     Source->getArgType(i), SourceLoc))
       return true;
@@ -487,15 +490,16 @@
   // This means that the source of the conversion can only throw a subset of
   // the exceptions of the target, and any exception specs on arguments or
   // return types must be equivalent.
-  return CheckExceptionSpecSubset(diag::err_incompatible_exception_specs,
-                                  0, ToFunc, From->getSourceRange().getBegin(),
+  return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),
+                                  PDiag(), ToFunc, 
+                                  From->getSourceRange().getBegin(),
                                   FromFunc, SourceLocation());
 }
 
 bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
                                                 const CXXMethodDecl *Old) {
-  return CheckExceptionSpecSubset(diag::err_override_exception_spec,
-                                  diag::note_overridden_virtual_function,
+  return CheckExceptionSpecSubset(PDiag(diag::err_override_exception_spec),
+                                  PDiag(diag::note_overridden_virtual_function),
                                   Old->getType()->getAs<FunctionProtoType>(),
                                   Old->getLocation(),
                                   New->getType()->getAs<FunctionProtoType>(),
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9dddc20..4bf26a5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2520,7 +2520,7 @@
                          SourceLocation OpLoc, const CXXScopeSpec &SS) {
   RecordDecl *RDecl = RTy->getDecl();
   if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
-                                  PDiag(diag::err_typecheck_incomplete_tag)
+                              SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
                                     << BaseRange))
     return true;
 
@@ -5785,7 +5785,7 @@
   case Expr::MLV_IncompleteType:
   case Expr::MLV_IncompleteVoidType:
     return S.RequireCompleteType(Loc, E->getType(),
-                PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue)
+              S.PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue)
                   << E->getSourceRange());
   case Expr::MLV_DuplicateVectorComponents:
     Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
@@ -6347,8 +6347,8 @@
 static void SuggestParentheses(Sema &Self, SourceLocation Loc,
                                const PartialDiagnostic &PD,
                                SourceRange ParenRange,
-                      const PartialDiagnostic &SecondPD = PartialDiagnostic(0),
-                               SourceRange SecondParenRange = SourceRange()) {
+                               const PartialDiagnostic &SecondPD,
+                               SourceRange SecondParenRange) {
   SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
   if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
     // We can't display the parentheses, so just dig the
@@ -6403,20 +6403,20 @@
 
   if (BinOp::isComparisonOp(lhsopc))
     SuggestParentheses(Self, OpLoc,
-      PDiag(diag::warn_precedence_bitwise_rel)
+      Self.PDiag(diag::warn_precedence_bitwise_rel)
           << SourceRange(lhs->getLocStart(), OpLoc)
           << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc),
       lhs->getSourceRange(),
-      PDiag(diag::note_precedence_bitwise_first)
+      Self.PDiag(diag::note_precedence_bitwise_first)
           << BinOp::getOpcodeStr(Opc),
       SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()));
   else if (BinOp::isComparisonOp(rhsopc))
     SuggestParentheses(Self, OpLoc,
-      PDiag(diag::warn_precedence_bitwise_rel)
+      Self.PDiag(diag::warn_precedence_bitwise_rel)
           << SourceRange(OpLoc, rhs->getLocEnd())
           << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc),
       rhs->getSourceRange(),
-      PDiag(diag::note_precedence_bitwise_first)
+      Self.PDiag(diag::note_precedence_bitwise_first)
         << BinOp::getOpcodeStr(Opc),
       SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()));
 }
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index bb67a75..58d7d67 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -4695,7 +4695,7 @@
     if (!ICS.isAmbiguous()) continue;
 
     S.DiagnoseAmbiguousConversion(ICS, OpLoc,
-                              PDiag(diag::note_ambiguous_type_conversion));
+                              S.PDiag(diag::note_ambiguous_type_conversion));
   }
 }
 
@@ -6135,7 +6135,7 @@
   DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
 
   if (RequireCompleteType(LParenLoc, Object->getType(), 
-                          PartialDiagnostic(diag::err_incomplete_object_call)
+                          PDiag(diag::err_incomplete_object_call)
                           << Object->getSourceRange()))
     return true;
   
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index fd65c32..733022a 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -427,7 +427,7 @@
   // Make sure that the condition expression has a complete type,
   // otherwise we'll never find any conversions.
   if (S.RequireCompleteType(SwitchLoc, CondType,
-                            PDiag(diag::err_switch_incomplete_class_type)
+                            S.PDiag(diag::err_switch_incomplete_class_type)
                               << CondExpr->getSourceRange()))
     return true;
 
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 08329e8..d1f0815 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -4067,11 +4067,11 @@
   UnresolvedSetIterator Result
     = getMostSpecialized(Candidates.begin(), Candidates.end(),
                          TPOC_Other, FD->getLocation(),
-                  PartialDiagnostic(diag::err_function_template_spec_no_match) 
+                  PDiag(diag::err_function_template_spec_no_match) 
                     << FD->getDeclName(),
-                  PartialDiagnostic(diag::err_function_template_spec_ambiguous)
+                  PDiag(diag::err_function_template_spec_ambiguous)
                     << FD->getDeclName() << (ExplicitTemplateArgs != 0),
-                  PartialDiagnostic(diag::note_function_template_spec_matched));
+                  PDiag(diag::note_function_template_spec_matched));
   if (Result == Candidates.end())
     return true;
 
@@ -4834,9 +4834,9 @@
   UnresolvedSetIterator Result
     = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 
                          D.getIdentifierLoc(), 
-          PartialDiagnostic(diag::err_explicit_instantiation_not_known) << Name,
-          PartialDiagnostic(diag::err_explicit_instantiation_ambiguous) << Name,
-                PartialDiagnostic(diag::note_explicit_instantiation_candidate));
+                     PDiag(diag::err_explicit_instantiation_not_known) << Name,
+                     PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
+                         PDiag(diag::note_explicit_instantiation_candidate));
 
   if (Result == Matches.end())
     return true;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index c7b1ef1..660718f 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1973,6 +1973,18 @@
   return true;
 }
 
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+                               const PartialDiagnostic &PD) {
+  return RequireCompleteType(Loc, T, PD, 
+                             std::make_pair(SourceLocation(), PDiag(0)));
+}
+  
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+                               unsigned DiagID) {
+  return RequireCompleteType(Loc, T, PDiag(DiagID),
+                             std::make_pair(SourceLocation(), PDiag(0)));
+}
+
 /// \brief Retrieve a version of the type 'T' that is qualified by the
 /// nested-name-specifier contained in SS.
 QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) {