Home | History | Annotate | Download | only in AST
      1 //===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- C++ -*-=//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file defines interfaces for diagnostics which may or may
     11 //  fire based on how a template is instantiated.
     12 //
     13 //  At the moment, the only consumer of this interface is access
     14 //  control.
     15 //
     16 //===----------------------------------------------------------------------===//
     17 
     18 #ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
     19 #define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
     20 
     21 #include "clang/AST/DeclBase.h"
     22 #include "clang/AST/DeclContextInternals.h"
     23 #include "clang/AST/Type.h"
     24 #include "clang/Basic/PartialDiagnostic.h"
     25 #include "clang/Basic/SourceLocation.h"
     26 
     27 namespace clang {
     28 
     29 class ASTContext;
     30 class CXXRecordDecl;
     31 class NamedDecl;
     32 
     33 /// A dependently-generated diagnostic.
     34 class DependentDiagnostic {
     35 public:
     36   enum AccessNonce { Access = 0 };
     37 
     38   static DependentDiagnostic *Create(ASTContext &Context,
     39                                      DeclContext *Parent,
     40                                      AccessNonce _,
     41                                      SourceLocation Loc,
     42                                      bool IsMemberAccess,
     43                                      AccessSpecifier AS,
     44                                      NamedDecl *TargetDecl,
     45                                      CXXRecordDecl *NamingClass,
     46                                      QualType BaseObjectType,
     47                                      const PartialDiagnostic &PDiag) {
     48     DependentDiagnostic *DD = Create(Context, Parent, PDiag);
     49     DD->AccessData.Loc = Loc.getRawEncoding();
     50     DD->AccessData.IsMember = IsMemberAccess;
     51     DD->AccessData.Access = AS;
     52     DD->AccessData.TargetDecl = TargetDecl;
     53     DD->AccessData.NamingClass = NamingClass;
     54     DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr();
     55     return DD;
     56   }
     57 
     58   unsigned getKind() const {
     59     return Access;
     60   }
     61 
     62   bool isAccessToMember() const {
     63     assert(getKind() == Access);
     64     return AccessData.IsMember;
     65   }
     66 
     67   AccessSpecifier getAccess() const {
     68     assert(getKind() == Access);
     69     return AccessSpecifier(AccessData.Access);
     70   }
     71 
     72   SourceLocation getAccessLoc() const {
     73     assert(getKind() == Access);
     74     return SourceLocation::getFromRawEncoding(AccessData.Loc);
     75   }
     76 
     77   NamedDecl *getAccessTarget() const {
     78     assert(getKind() == Access);
     79     return AccessData.TargetDecl;
     80   }
     81 
     82   NamedDecl *getAccessNamingClass() const {
     83     assert(getKind() == Access);
     84     return AccessData.NamingClass;
     85   }
     86 
     87   QualType getAccessBaseObjectType() const {
     88     assert(getKind() == Access);
     89     return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
     90   }
     91 
     92   const PartialDiagnostic &getDiagnostic() const {
     93     return Diag;
     94   }
     95 
     96 private:
     97   DependentDiagnostic(const PartialDiagnostic &PDiag,
     98                       PartialDiagnostic::Storage *Storage)
     99     : Diag(PDiag, Storage) {}
    100 
    101   static DependentDiagnostic *Create(ASTContext &Context,
    102                                      DeclContext *Parent,
    103                                      const PartialDiagnostic &PDiag);
    104 
    105   friend class DependentStoredDeclsMap;
    106   friend class DeclContext::ddiag_iterator;
    107   DependentDiagnostic *NextDiagnostic;
    108 
    109   PartialDiagnostic Diag;
    110 
    111   struct {
    112     unsigned Loc;
    113     unsigned Access : 2;
    114     unsigned IsMember : 1;
    115     NamedDecl *TargetDecl;
    116     CXXRecordDecl *NamingClass;
    117     void *BaseObjectType;
    118   } AccessData;
    119 };
    120 
    121 ///
    122 
    123 /// An iterator over the dependent diagnostics in a dependent context.
    124 class DeclContext::ddiag_iterator {
    125 public:
    126   ddiag_iterator() : Ptr(nullptr) {}
    127   explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
    128 
    129   typedef DependentDiagnostic *value_type;
    130   typedef DependentDiagnostic *reference;
    131   typedef DependentDiagnostic *pointer;
    132   typedef int difference_type;
    133   typedef std::forward_iterator_tag iterator_category;
    134 
    135   reference operator*() const { return Ptr; }
    136 
    137   ddiag_iterator &operator++() {
    138     assert(Ptr && "attempt to increment past end of diag list");
    139     Ptr = Ptr->NextDiagnostic;
    140     return *this;
    141   }
    142 
    143   ddiag_iterator operator++(int) {
    144     ddiag_iterator tmp = *this;
    145     ++*this;
    146     return tmp;
    147   }
    148 
    149   bool operator==(ddiag_iterator Other) const {
    150     return Ptr == Other.Ptr;
    151   }
    152 
    153   bool operator!=(ddiag_iterator Other) const {
    154     return Ptr != Other.Ptr;
    155   }
    156 
    157   ddiag_iterator &operator+=(difference_type N) {
    158     assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
    159     while (N--)
    160       ++*this;
    161     return *this;
    162   }
    163 
    164   ddiag_iterator operator+(difference_type N) const {
    165     ddiag_iterator tmp = *this;
    166     tmp += N;
    167     return tmp;
    168   }
    169 
    170 private:
    171   DependentDiagnostic *Ptr;
    172 };
    173 
    174 inline DeclContext::ddiag_range DeclContext::ddiags() const {
    175   assert(isDependentContext()
    176          && "cannot iterate dependent diagnostics of non-dependent context");
    177   const DependentStoredDeclsMap *Map
    178     = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr());
    179 
    180   if (!Map)
    181     // Return an empty range using the always-end default constructor.
    182     return ddiag_range(ddiag_iterator(), ddiag_iterator());
    183 
    184   return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator());
    185 }
    186 
    187 }
    188 
    189 #endif
    190