]> granicus.if.org Git - clang/commitdiff
Optimize PartialDiagnostic's memory-allocation behavior by placing a
authorDouglas Gregor <dgregor@apple.com>
Mon, 29 Mar 2010 23:34:08 +0000 (23:34 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 29 Mar 2010 23:34:08 +0000 (23:34 +0000)
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

14 files changed:
include/clang/AST/ASTContext.h
include/clang/Basic/PartialDiagnostic.h
lib/AST/DeclBase.cpp
lib/Basic/Diagnostic.cpp
lib/Sema/Sema.h
lib/Sema/SemaAccess.cpp
lib/Sema/SemaCXXCast.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExceptionSpec.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaType.cpp

index 79988e6148aa93f8dea8365aa15a71980f72555e..22aec7f5bea198beb3edf8dd83b96e099e8c3f2f 100644 (file)
@@ -17,6 +17,7 @@
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/PartialDiagnostic.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/NestedNameSpecifier.h"
@@ -265,6 +266,9 @@ class ASTContext {
   llvm::MallocAllocator MallocAlloc;
   llvm::BumpPtrAllocator BumpAlloc;
 
+  /// \brief Allocator for partial diagnostics.
+  PartialDiagnostic::StorageAllocator DiagAllocator;
+  
 public:
   const TargetInfo &Target;
   IdentifierTable &Idents;
@@ -290,6 +294,11 @@ public:
     if (FreeMemory)
       MallocAlloc.Deallocate(Ptr);
   }
+  
+  PartialDiagnostic::StorageAllocator &getDiagAllocator() {
+    return DiagAllocator;
+  }
+
   const LangOptions& getLangOptions() const { return LangOpts; }
 
   FullSourceLoc getFullLoc(SourceLocation Loc) const {
index fb861dcf934d23320ef10512f044b4f6bd0376ed..56082b7b09f4fe76a61e05c2ec23fa5bee9c6f33 100644 (file)
@@ -69,6 +69,43 @@ class PartialDiagnostic {
     CodeModificationHint CodeModificationHints[MaxCodeModificationHints];    
   };
 
+public:
+  /// \brief An allocator for Storage objects, which uses a small cache to 
+  /// objects, used to reduce malloc()/free() traffic for partial diagnostics.
+  class StorageAllocator {
+    static const unsigned NumCached = 4;
+    Storage Cached[NumCached];
+    Storage *FreeList[NumCached];
+    unsigned NumFreeListEntries;
+    
+  public:
+    StorageAllocator();
+    ~StorageAllocator();
+    
+    /// \brief Allocate new storage.
+    Storage *Allocate() {
+      if (NumFreeListEntries == 0)
+        return new Storage;
+      
+      Storage *Result = FreeList[--NumFreeListEntries];
+      Result->NumDiagArgs = 0;
+      Result->NumDiagRanges = 0;
+      Result->NumCodeModificationHints = 0;
+      return Result;
+    }
+    
+    /// \brief Free the given storage object.
+    void Deallocate(Storage *S) {
+      if (S >= Cached && S <= Cached + NumCached) {
+        FreeList[NumFreeListEntries++] = S;
+        return;
+      }
+      
+      delete S;
+    }
+  };
+  
+private:
   // NOTE: Sema assumes that PartialDiagnostic is location-invariant
   // in the sense that its bits can be safely memcpy'ed and destructed
   // in the new location.
@@ -76,12 +113,38 @@ class PartialDiagnostic {
   /// DiagID - The diagnostic ID.
   mutable unsigned DiagID;
   
-  /// DiagStorare - Storge for args and ranges.
+  /// DiagStorage - Storage for args and ranges.
   mutable Storage *DiagStorage;
 
+  /// \brief Allocator used to allocate storage for this diagnostic.
+  StorageAllocator *Allocator;
+  
+  /// \brief Retrieve storage for this particular diagnostic.
+  Storage *getStorage() const {
+    if (DiagStorage)
+      return DiagStorage;
+    
+    if (Allocator)
+      DiagStorage = Allocator->Allocate();
+    else
+      DiagStorage = new Storage;
+    return DiagStorage;
+  }
+  
+  void freeStorage() { 
+    if (!DiagStorage)
+      return;
+    
+    if (Allocator)
+      Allocator->Deallocate(DiagStorage);
+    else
+      delete DiagStorage;
+    DiagStorage = 0;
+  }
+  
   void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
     if (!DiagStorage)
-      DiagStorage = new Storage;
+      DiagStorage = getStorage();
     
     assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
            "Too many arguments to diagnostic!");
@@ -91,7 +154,7 @@ class PartialDiagnostic {
 
   void AddSourceRange(const SourceRange &R) const {
     if (!DiagStorage)
-      DiagStorage = new Storage;
+      DiagStorage = getStorage();
 
     assert(DiagStorage->NumDiagRanges < 
            llvm::array_lengthof(DiagStorage->DiagRanges) &&
@@ -104,7 +167,7 @@ class PartialDiagnostic {
       return;
     
     if (!DiagStorage)
-      DiagStorage = new Storage;
+      DiagStorage = getStorage();
 
     assert(DiagStorage->NumCodeModificationHints < 
              Storage::MaxCodeModificationHints &&
@@ -114,36 +177,36 @@ class PartialDiagnostic {
   }
   
 public:
-  PartialDiagnostic(unsigned DiagID)
-    : DiagID(DiagID), DiagStorage(0) { }
-
+  PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator)
+    : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { }
+  
   PartialDiagnostic(const PartialDiagnostic &Other) 
-    : DiagID(Other.DiagID), DiagStorage(0) 
+    : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator)
   {
-    if (Other.DiagStorage)
-      DiagStorage = new Storage(*Other.DiagStorage);
+    if (Other.DiagStorage) {
+      DiagStorage = getStorage();
+      *DiagStorage = *Other.DiagStorage;
+    }
   }
 
   PartialDiagnostic &operator=(const PartialDiagnostic &Other) {
     DiagID = Other.DiagID;
     if (Other.DiagStorage) {
-      if (DiagStorage)
-        *DiagStorage = *Other.DiagStorage;
-      else
-        DiagStorage = new Storage(*Other.DiagStorage);
+      if (!DiagStorage)
+        DiagStorage = getStorage();
+      
+      *DiagStorage = *Other.DiagStorage;
     } else {
-      delete DiagStorage;
-      DiagStorage = 0;
+      freeStorage();
     }
 
     return *this;
   }
 
   ~PartialDiagnostic() {
-    delete DiagStorage;
+    freeStorage();
   }
 
-
   unsigned getDiagID() const { return DiagID; }
 
   void Emit(const DiagnosticBuilder &DB) const {
@@ -165,6 +228,13 @@ public:
       DB.AddCodeModificationHint(DiagStorage->CodeModificationHints[i]);
   }
   
+  /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID
+  /// and removing all of its arguments, ranges, and fix-it hints.
+  void Reset(unsigned DiagID = 0) {
+    this->DiagID = DiagID;
+    freeStorage();
+  }
+  
   friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
                                              QualType T) {
     PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
@@ -207,10 +277,6 @@ public:
   
 };
 
-inline PartialDiagnostic PDiag(unsigned DiagID = 0) {
-  return PartialDiagnostic(DiagID);
-}
-
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
                                            const PartialDiagnostic &PD) {
   PD.Emit(DB);
index 9e92855681b4691a1334ebecfdfaffea4f8a2cb1..cb6b76c24872f5fc56fa5925fba34c9552024faf 100644 (file)
@@ -1017,6 +1017,8 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
   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.
index 21a8aeae429ffdd06019b6307a2764cbae9f4112..9b8bae31427a3b52f99d906f562cceff8377e835 100644 (file)
@@ -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 @@ StoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM,
 ///  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");
+}
index 9c661ba1b13658f1141190765f1e52b5ab745b93..859e4975764a659e4a676c79e29c01dddb469811 100644 (file)
@@ -312,30 +312,33 @@ public:
 
     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 @@ public:
     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 @@ public:
   /// \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 @@ public:
 
   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);
index 9ceb17cd0f8ff1af56e0d1aa7ae45684343a5931..e7ea2041370cb5dc036a9f265626fd5ae7d6c586 100644 (file)
@@ -768,14 +768,16 @@ void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
   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 @@ Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
       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 @@ Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
       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 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
     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 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
     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 @@ Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
     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 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
       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 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
   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 @@ Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
   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 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
 
   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);
index 285ee4945d8bf6b4730ce8639976803de92b4489..2b93d38e2abbaadb661a3cde40847749319ec4ab 100644 (file)
@@ -315,7 +315,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
     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 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
   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 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
                   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.
index a7671a2cf8a886684e5a52565ace51243303567c..efd34f93c9cd6e2d6db46a138d82c665f8bacc66 100644 (file)
@@ -1865,7 +1865,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
     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 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
     // 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 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
     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 @@ void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
 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 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
                                   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 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
                                   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 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
         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 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
           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 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
     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());
   }
index 5767551c53b8d76e6a0083eb5e66c5fefa0b442d..eae30dc97295a9c1f9a8e2fc097f22c6ca898a4e 100644 (file)
@@ -98,8 +98,8 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {
 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(FunctionDecl *Old, FunctionDecl *New) {
 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 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
     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 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
          "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 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
   // 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>(),
index 9dddc2093afe255e11234a578d4139c94cfc0805..4bf26a5224e700973225fc74b92a138c526a0949 100644 (file)
@@ -2520,7 +2520,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
                          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 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
   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 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
 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 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc,
 
   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()));
 }
index bb67a759726d229e1fe66a7f351167bc9cfb7f58..58d7d6750855ab5f77fe4473593a57ead1049dc1 100644 (file)
@@ -4695,7 +4695,7 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
     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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
   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;
   
index fd65c32c203e958955cdca428958575d6f225c2a..733022aac354005e136e2b14e2eaa5fc16f3724f 100644 (file)
@@ -427,7 +427,7 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc,
   // 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;
 
index 08329e899666d9a6272a2bb6dbc06e4a636c923e..d1f0815eae5376a5102e5f8b74e56931dd430010 100644 (file)
@@ -4067,11 +4067,11 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
   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 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
   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;
index c7b1ef15aa7606b62fae9b56b50208173b7f45a1..660718f98f96eef7b2212d75280bf83daf0e9d70 100644 (file)
@@ -1973,6 +1973,18 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
   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) {