clang API Documentation

DependentDiagnostic.h
Go to the documentation of this file.
00001 //===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- C++ -*-=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines interfaces for diagnostics which may or may
00011 //  fire based on how a template is instantiated.
00012 //
00013 //  At the moment, the only consumer of this interface is access
00014 //  control.
00015 //
00016 //===----------------------------------------------------------------------===//
00017 
00018 #ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
00019 #define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
00020 
00021 #include "clang/Basic/PartialDiagnostic.h"
00022 #include "clang/Basic/SourceLocation.h"
00023 #include "clang/AST/DeclBase.h"
00024 #include "clang/AST/DeclContextInternals.h"
00025 #include "clang/AST/Type.h"
00026 
00027 namespace clang {
00028 
00029 class ASTContext;
00030 class CXXRecordDecl;
00031 class NamedDecl;
00032 
00033 /// A dependently-generated diagnostic.
00034 class DependentDiagnostic {
00035 public:
00036   enum AccessNonce { Access = 0 };
00037 
00038   static DependentDiagnostic *Create(ASTContext &Context,
00039                                      DeclContext *Parent,
00040                                      AccessNonce _,
00041                                      SourceLocation Loc,
00042                                      bool IsMemberAccess,
00043                                      AccessSpecifier AS,
00044                                      NamedDecl *TargetDecl,
00045                                      CXXRecordDecl *NamingClass,
00046                                      QualType BaseObjectType,
00047                                      const PartialDiagnostic &PDiag) {
00048     DependentDiagnostic *DD = Create(Context, Parent, PDiag);
00049     DD->AccessData.Loc = Loc.getRawEncoding();
00050     DD->AccessData.IsMember = IsMemberAccess;
00051     DD->AccessData.Access = AS;
00052     DD->AccessData.TargetDecl = TargetDecl;
00053     DD->AccessData.NamingClass = NamingClass;
00054     DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr();
00055     return DD;
00056   }
00057 
00058   unsigned getKind() const {
00059     return Access;
00060   }
00061 
00062   bool isAccessToMember() const {
00063     assert(getKind() == Access);
00064     return AccessData.IsMember;
00065   }
00066 
00067   AccessSpecifier getAccess() const {
00068     assert(getKind() == Access);
00069     return AccessSpecifier(AccessData.Access);
00070   }
00071 
00072   SourceLocation getAccessLoc() const {
00073     assert(getKind() == Access);
00074     return SourceLocation::getFromRawEncoding(AccessData.Loc);
00075   }
00076 
00077   NamedDecl *getAccessTarget() const {
00078     assert(getKind() == Access);
00079     return AccessData.TargetDecl;
00080   }
00081 
00082   NamedDecl *getAccessNamingClass() const {
00083     assert(getKind() == Access);
00084     return AccessData.NamingClass;
00085   }
00086 
00087   QualType getAccessBaseObjectType() const {
00088     assert(getKind() == Access);
00089     return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
00090   }
00091 
00092   const PartialDiagnostic &getDiagnostic() const {
00093     return Diag;
00094   }
00095 
00096 private:
00097   DependentDiagnostic(const PartialDiagnostic &PDiag,
00098                       PartialDiagnostic::Storage *Storage) 
00099     : Diag(PDiag, Storage) {}
00100   
00101   static DependentDiagnostic *Create(ASTContext &Context,
00102                                      DeclContext *Parent,
00103                                      const PartialDiagnostic &PDiag);
00104 
00105   friend class DependentStoredDeclsMap;
00106   friend class DeclContext::ddiag_iterator;
00107   DependentDiagnostic *NextDiagnostic;
00108 
00109   PartialDiagnostic Diag;
00110 
00111   union {
00112     struct {
00113       unsigned Loc;
00114       unsigned Access : 2;
00115       unsigned IsMember : 1;
00116       NamedDecl *TargetDecl;
00117       CXXRecordDecl *NamingClass;
00118       void *BaseObjectType;
00119     } AccessData;
00120   };
00121 };
00122 
00123 /// 
00124 
00125 /// An iterator over the dependent diagnostics in a dependent context.
00126 class DeclContext::ddiag_iterator {
00127 public:
00128   ddiag_iterator() : Ptr(0) {}
00129   explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
00130 
00131   typedef DependentDiagnostic *value_type;
00132   typedef DependentDiagnostic *reference;
00133   typedef DependentDiagnostic *pointer;
00134   typedef int difference_type;
00135   typedef std::forward_iterator_tag iterator_category;
00136 
00137   reference operator*() const { return Ptr; }
00138 
00139   ddiag_iterator &operator++() {
00140     assert(Ptr && "attempt to increment past end of diag list");
00141     Ptr = Ptr->NextDiagnostic;
00142     return *this;
00143   }
00144 
00145   ddiag_iterator operator++(int) {
00146     ddiag_iterator tmp = *this;
00147     ++*this;
00148     return tmp;
00149   }
00150 
00151   bool operator==(ddiag_iterator Other) const {
00152     return Ptr == Other.Ptr;
00153   }
00154 
00155   bool operator!=(ddiag_iterator Other) const {
00156     return Ptr != Other.Ptr;
00157   }
00158 
00159   ddiag_iterator &operator+=(difference_type N) {
00160     assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
00161     while (N--)
00162       ++*this;
00163     return *this;
00164   }
00165 
00166   ddiag_iterator operator+(difference_type N) const {
00167     ddiag_iterator tmp = *this;
00168     tmp += N;
00169     return tmp;
00170   }
00171 
00172 private:
00173   DependentDiagnostic *Ptr;
00174 };
00175 
00176 inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const {
00177   assert(isDependentContext()
00178          && "cannot iterate dependent diagnostics of non-dependent context");
00179   const DependentStoredDeclsMap *Map
00180     = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr());
00181 
00182   if (!Map) return ddiag_iterator();
00183   return ddiag_iterator(Map->FirstDiagnostic);
00184 }
00185 
00186 inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const {
00187   return ddiag_iterator();
00188 }
00189 
00190 }
00191 
00192 #endif