summaryrefslogtreecommitdiffstats
path: root/build/clang-plugin/CustomTypeAnnotation.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /build/clang-plugin/CustomTypeAnnotation.cpp
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'build/clang-plugin/CustomTypeAnnotation.cpp')
-rw-r--r--build/clang-plugin/CustomTypeAnnotation.cpp182
1 files changed, 182 insertions, 0 deletions
diff --git a/build/clang-plugin/CustomTypeAnnotation.cpp b/build/clang-plugin/CustomTypeAnnotation.cpp
new file mode 100644
index 0000000000..6e0f44ce05
--- /dev/null
+++ b/build/clang-plugin/CustomTypeAnnotation.cpp
@@ -0,0 +1,182 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CustomTypeAnnotation.h"
+#include "Utils.h"
+
+CustomTypeAnnotation StackClass =
+ CustomTypeAnnotation(moz_stack_class, "stack");
+CustomTypeAnnotation GlobalClass =
+ CustomTypeAnnotation(moz_global_class, "global");
+CustomTypeAnnotation NonHeapClass =
+ CustomTypeAnnotation(moz_nonheap_class, "non-heap");
+CustomTypeAnnotation HeapClass = CustomTypeAnnotation(moz_heap_class, "heap");
+CustomTypeAnnotation NonTemporaryClass =
+ CustomTypeAnnotation(moz_non_temporary_class, "non-temporary");
+CustomTypeAnnotation TemporaryClass =
+ CustomTypeAnnotation(moz_temporary_class, "temporary");
+CustomTypeAnnotation StaticLocalClass =
+ CustomTypeAnnotation(moz_static_local_class, "static-local");
+
+void CustomTypeAnnotation::dumpAnnotationReason(BaseCheck &Check, QualType T,
+ SourceLocation Loc) {
+ const char *Inherits =
+ "%1 is a %0 type because it inherits from a %0 type %2";
+ const char *Member = "%1 is a %0 type because member %2 is a %0 type %3";
+ const char *Array = "%1 is a %0 type because it is an array of %0 type %2";
+ const char *Templ =
+ "%1 is a %0 type because it has a template argument %0 type %2";
+ const char *Implicit = "%1 is a %0 type because %2";
+
+ AnnotationReason Reason = directAnnotationReason(T);
+ for (;;) {
+ switch (Reason.Kind) {
+ case RK_ArrayElement:
+ Check.diag(Loc, Array, DiagnosticIDs::Note) << Pretty << T << Reason.Type;
+ break;
+ case RK_BaseClass: {
+ const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl();
+ assert(Declaration && "This type should be a C++ class");
+
+ Check.diag(Declaration->getLocation(), Inherits, DiagnosticIDs::Note)
+ << Pretty << T << Reason.Type;
+ break;
+ }
+ case RK_Field:
+ Check.diag(Reason.Field->getLocation(), Member, DiagnosticIDs::Note)
+ << Pretty << T << Reason.Field << Reason.Type;
+ break;
+ case RK_TemplateInherited: {
+ const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl();
+ assert(Declaration && "This type should be a C++ class");
+
+ Check.diag(Declaration->getLocation(), Templ, DiagnosticIDs::Note)
+ << Pretty << T << Reason.Type;
+ break;
+ }
+ case RK_Implicit: {
+ const TagDecl *Declaration = T->getAsTagDecl();
+ assert(Declaration && "This type should be a TagDecl");
+
+ Check.diag(Declaration->getLocation(), Implicit, DiagnosticIDs::Note)
+ << Pretty << T << Reason.ImplicitReason;
+ return;
+ }
+ default:
+ // FIXME (bug 1203263): note the original annotation.
+ return;
+ }
+
+ T = Reason.Type;
+ Reason = directAnnotationReason(T);
+ }
+}
+
+CustomTypeAnnotation::AnnotationReason
+CustomTypeAnnotation::directAnnotationReason(QualType T) {
+ VisitFlags ToVisit = VISIT_FIELDS | VISIT_BASES;
+
+ if (const TagDecl *D = T->getAsTagDecl()) {
+ // Recurse into template arguments if the annotation
+ // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
+ if (hasCustomAttribute<moz_inherit_type_annotations_from_template_args>(
+ D)) {
+ ToVisit |= VISIT_TMPL_ARGS;
+ }
+
+ if (hasCustomAttribute(D, Attribute)) {
+ AnnotationReason Reason = {T, RK_Direct, nullptr, ""};
+ return Reason;
+ }
+
+ std::string ImplAnnotReason = getImplicitReason(D, ToVisit);
+ if (!ImplAnnotReason.empty()) {
+ AnnotationReason Reason = {T, RK_Implicit, nullptr, ImplAnnotReason};
+ return Reason;
+ }
+ }
+
+ // Check if we have a cached answer
+ void *Key = T.getAsOpaquePtr();
+ ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr());
+ if (Cached != Cache.end()) {
+ return Cached->second;
+ }
+
+ // Check if we have a type which we can recurse into
+ if (const clang::ArrayType *Array = T->getAsArrayTypeUnsafe()) {
+ if (hasEffectiveAnnotation(Array->getElementType())) {
+ AnnotationReason Reason{Array->getElementType(), RK_ArrayElement, nullptr,
+ ""};
+ Cache[Key] = Reason;
+ return Reason;
+ }
+ }
+
+ // Recurse into Base classes
+ if (const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl()) {
+ if (Declaration->hasDefinition()) {
+ Declaration = Declaration->getDefinition();
+
+ if (ToVisit & VISIT_BASES) {
+ for (const CXXBaseSpecifier &Base : Declaration->bases()) {
+ if (hasEffectiveAnnotation(Base.getType())) {
+ AnnotationReason Reason{Base.getType(), RK_BaseClass, nullptr, ""};
+ Cache[Key] = Reason;
+ return Reason;
+ }
+ }
+ }
+
+ if (ToVisit & VISIT_FIELDS) {
+ for (const FieldDecl *Field : Declaration->fields()) {
+ if (hasEffectiveAnnotation(Field->getType())) {
+ AnnotationReason Reason{Field->getType(), RK_Field, Field, ""};
+ Cache[Key] = Reason;
+ return Reason;
+ }
+ }
+ }
+
+ if (ToVisit & VISIT_TMPL_ARGS) {
+ const ClassTemplateSpecializationDecl *Spec =
+ dyn_cast<ClassTemplateSpecializationDecl>(Declaration);
+ if (Spec) {
+ const TemplateArgumentList &Args = Spec->getTemplateArgs();
+
+ AnnotationReason Reason = tmplArgAnnotationReason(Args.asArray());
+ if (Reason.Kind != RK_None) {
+ Cache[Key] = Reason;
+ return Reason;
+ }
+ }
+ }
+ }
+ }
+
+ AnnotationReason Reason{QualType(), RK_None, nullptr, ""};
+ Cache[Key] = Reason;
+ return Reason;
+}
+
+CustomTypeAnnotation::AnnotationReason
+CustomTypeAnnotation::tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args) {
+ for (const TemplateArgument &Arg : Args) {
+ if (Arg.getKind() == TemplateArgument::Type) {
+ QualType Type = Arg.getAsType();
+ if (hasEffectiveAnnotation(Type)) {
+ AnnotationReason Reason = {Type, RK_TemplateInherited, nullptr, ""};
+ return Reason;
+ }
+ } else if (Arg.getKind() == TemplateArgument::Pack) {
+ AnnotationReason Reason = tmplArgAnnotationReason(Arg.getPackAsArray());
+ if (Reason.Kind != RK_None) {
+ return Reason;
+ }
+ }
+ }
+
+ AnnotationReason Reason = {QualType(), RK_None, nullptr, ""};
+ return Reason;
+}