diff options
Diffstat (limited to 'include/clang/Sema/DelayedDiagnostic.h')
-rw-r--r-- | include/clang/Sema/DelayedDiagnostic.h | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h new file mode 100644 index 000000000000..6a9a1bf5b608 --- /dev/null +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -0,0 +1,168 @@ +//===--- DelayedDiagnostic.h - Delayed declarator diagnostics ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DelayedDiagnostic class, which is used to +// record diagnostics that are being conditionally produced during +// declarator parsing. Certain kinds of diagnostics --- notably +// deprecation and access control --- are suppressed based on +// semantic properties of the parsed declaration that aren't known +// until it is fully parsed. +// +// This file also defines AccessedEntity. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H +#define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H + +#include "clang/AST/DeclCXX.h" + +namespace clang { +namespace sema { + +/// A declaration being accessed, together with information about how +/// it was accessed. +class AccessedEntity { +public: + /// A member declaration found through lookup. The target is the + /// member. + enum MemberNonce { Member }; + + /// A hierarchy (base-to-derived or derived-to-base) conversion. + /// The target is the base class. + enum BaseNonce { Base }; + + bool isMemberAccess() const { return IsMember; } + + AccessedEntity(ASTContext &Context, + MemberNonce _, + CXXRecordDecl *NamingClass, + DeclAccessPair FoundDecl, + QualType BaseObjectType) + : Access(FoundDecl.getAccess()), IsMember(true), + Target(FoundDecl.getDecl()), NamingClass(NamingClass), + BaseObjectType(BaseObjectType), Diag(0, Context.getDiagAllocator()) { + } + + AccessedEntity(ASTContext &Context, + BaseNonce _, + CXXRecordDecl *BaseClass, + CXXRecordDecl *DerivedClass, + AccessSpecifier Access) + : Access(Access), IsMember(false), + Target(BaseClass), + NamingClass(DerivedClass), + Diag(0, Context.getDiagAllocator()) { + } + + bool isQuiet() const { return Diag.getDiagID() == 0; } + + AccessSpecifier getAccess() const { return AccessSpecifier(Access); } + + // These apply to member decls... + NamedDecl *getTargetDecl() const { return Target; } + CXXRecordDecl *getNamingClass() const { return NamingClass; } + + // ...and these apply to hierarchy conversions. + CXXRecordDecl *getBaseClass() const { + assert(!IsMember); return cast<CXXRecordDecl>(Target); + } + CXXRecordDecl *getDerivedClass() const { return NamingClass; } + + /// Retrieves the base object type, important when accessing + /// an instance member. + QualType getBaseObjectType() const { return BaseObjectType; } + + /// Sets a diagnostic to be performed. The diagnostic is given + /// four (additional) arguments: + /// %0 - 0 if the entity was private, 1 if protected + /// %1 - the DeclarationName of the entity + /// %2 - the TypeDecl type of the naming class + /// %3 - the TypeDecl type of the declaring class + void setDiag(const PartialDiagnostic &PDiag) { + assert(isQuiet() && "partial diagnostic already defined"); + Diag = PDiag; + } + PartialDiagnostic &setDiag(unsigned DiagID) { + assert(isQuiet() && "partial diagnostic already defined"); + assert(DiagID && "creating null diagnostic"); + Diag.Reset(DiagID); + return Diag; + } + const PartialDiagnostic &getDiag() const { + return Diag; + } + +private: + unsigned Access : 2; + bool IsMember; + NamedDecl *Target; + CXXRecordDecl *NamingClass; + QualType BaseObjectType; + PartialDiagnostic Diag; +}; + +/// A diagnostic message which has been conditionally emitted pending +/// the complete parsing of the current declaration. +class DelayedDiagnostic { +public: + enum DDKind { Deprecation, Access }; + + unsigned char Kind; // actually a DDKind + bool Triggered; + + SourceLocation Loc; + + union { + /// Deprecation. + struct { NamedDecl *Decl; } DeprecationData; + + /// Access control. + char AccessData[sizeof(AccessedEntity)]; + }; + + void destroy() { + switch (Kind) { + case Access: getAccessData().~AccessedEntity(); break; + case Deprecation: break; + } + } + + static DelayedDiagnostic makeDeprecation(SourceLocation Loc, + NamedDecl *D) { + DelayedDiagnostic DD; + DD.Kind = Deprecation; + DD.Triggered = false; + DD.Loc = Loc; + DD.DeprecationData.Decl = D; + return DD; + } + + static DelayedDiagnostic makeAccess(SourceLocation Loc, + const AccessedEntity &Entity) { + DelayedDiagnostic DD; + DD.Kind = Access; + DD.Triggered = false; + DD.Loc = Loc; + new (&DD.getAccessData()) AccessedEntity(Entity); + return DD; + } + + AccessedEntity &getAccessData() { + return *reinterpret_cast<AccessedEntity*>(AccessData); + } + const AccessedEntity &getAccessData() const { + return *reinterpret_cast<const AccessedEntity*>(AccessData); + } +}; + +} +} + +#endif |