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