aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Sema/DelayedDiagnostic.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Sema/DelayedDiagnostic.h')
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h168
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