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_DEPENDENT_DIAGNOSTIC_H 19 #define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H 20 21 #include "clang/Basic/PartialDiagnostic.h" 22 #include "clang/Basic/SourceLocation.h" 23 #include "clang/AST/DeclBase.h" 24 #include "clang/AST/DeclContextInternals.h" 25 #include "clang/AST/Type.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 union { 112 struct { 113 unsigned Loc; 114 unsigned Access : 2; 115 unsigned IsMember : 1; 116 NamedDecl *TargetDecl; 117 CXXRecordDecl *NamingClass; 118 void *BaseObjectType; 119 } AccessData; 120 }; 121 }; 122 123 /// 124 125 /// An iterator over the dependent diagnostics in a dependent context. 126 class DeclContext::ddiag_iterator { 127 public: 128 ddiag_iterator() : Ptr(0) {} 129 explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {} 130 131 typedef DependentDiagnostic *value_type; 132 typedef DependentDiagnostic *reference; 133 typedef DependentDiagnostic *pointer; 134 typedef int difference_type; 135 typedef std::forward_iterator_tag iterator_category; 136 137 reference operator*() const { return Ptr; } 138 139 ddiag_iterator &operator++() { 140 assert(Ptr && "attempt to increment past end of diag list"); 141 Ptr = Ptr->NextDiagnostic; 142 return *this; 143 } 144 145 ddiag_iterator operator++(int) { 146 ddiag_iterator tmp = *this; 147 ++*this; 148 return tmp; 149 } 150 151 bool operator==(ddiag_iterator Other) const { 152 return Ptr == Other.Ptr; 153 } 154 155 bool operator!=(ddiag_iterator Other) const { 156 return Ptr != Other.Ptr; 157 } 158 159 ddiag_iterator &operator+=(difference_type N) { 160 assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator"); 161 while (N--) 162 ++*this; 163 return *this; 164 } 165 166 ddiag_iterator operator+(difference_type N) const { 167 ddiag_iterator tmp = *this; 168 tmp += N; 169 return tmp; 170 } 171 172 private: 173 DependentDiagnostic *Ptr; 174 }; 175 176 inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const { 177 assert(isDependentContext() 178 && "cannot iterate dependent diagnostics of non-dependent context"); 179 const DependentStoredDeclsMap *Map 180 = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->LookupPtr); 181 182 if (!Map) return ddiag_iterator(); 183 return ddiag_iterator(Map->FirstDiagnostic); 184 } 185 186 inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const { 187 return ddiag_iterator(); 188 } 189 190 } 191 192 #endif 193