Bug 1209227 - Part 1: Make the MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS analysis handle packs more correctly, r=ehsan
authorMichael Layzell <michael@thelayzells.com>
Tue, 29 Sep 2015 13:36:28 -0400
changeset 298151 ed89ff77c920a87da224befbe848b8cd6497fb46
parent 298150 8550398c99fb9529416a034f6310fd2c5d0911d4
child 298152 e12e09384b27f84b34145ced24af38607c378b87
push id30273
push userkwierso@gmail.com
push dateFri, 20 May 2016 21:08:12 +0000
treeherdermozilla-central@c403ac05b8f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1209227
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1209227 - Part 1: Make the MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS analysis handle packs more correctly, r=ehsan
build/clang-plugin/clang-plugin.cpp
build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp
--- a/build/clang-plugin/clang-plugin.cpp
+++ b/build/clang-plugin/clang-plugin.cpp
@@ -314,16 +314,17 @@ public:
       Diag.Report(Loc, NoteID);
       dumpAnnotationReason(Diag, T, Loc);
     }
   }
 
 private:
   bool hasLiteralAnnotation(QualType T) const;
   AnnotationReason directAnnotationReason(QualType T);
+  AnnotationReason tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args);
 
 protected:
   // Allow subclasses to apply annotations to external code:
   virtual bool hasFakeAnnotation(const TagDecl *D) const { return false; }
 };
 
 static CustomTypeAnnotation StackClass =
     CustomTypeAnnotation("moz_stack_class", "stack");
@@ -877,37 +878,52 @@ CustomTypeAnnotation::directAnnotationRe
       // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
       if (MozChecker::hasCustomAnnotation(
               Decl, "moz_inherit_type_annotations_from_template_args")) {
         const ClassTemplateSpecializationDecl *Spec =
             dyn_cast<ClassTemplateSpecializationDecl>(Decl);
         if (Spec) {
           const TemplateArgumentList &Args = Spec->getTemplateArgs();
 
-          for (const TemplateArgument &Arg : Args.asArray()) {
-            if (Arg.getKind() == TemplateArgument::Type) {
-              QualType Type = Arg.getAsType();
-
-              if (hasEffectiveAnnotation(Type)) {
-                AnnotationReason Reason = {Type, RK_TemplateInherited, nullptr};
-                Cache[Key] = Reason;
-                return Reason;
-              }
-            }
+          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;
+}
+
 bool isPlacementNew(const CXXNewExpr *Expr) {
   // Regular new expressions aren't placement new
   if (Expr->getNumPlacementArgs() == 0)
     return false;
   const FunctionDecl *Decl = Expr->getOperatorNew();
   if (Decl && MozChecker::hasCustomAnnotation(Decl, "moz_heap_allocator")) {
     return false;
   }
--- a/build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp
+++ b/build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp
@@ -20,18 +20,27 @@ class ContainsTemplate { Template<Stack>
 static Template<Stack> a; // expected-error {{variable of type 'Template<Stack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
 static Template<IndirectStack> b; // expected-error {{variable of type 'Template<IndirectStack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
 static Template<ContainsStack> c; // expected-error {{variable of type 'Template<ContainsStack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
 static IndirectTemplate d; // expected-error {{variable of type 'IndirectTemplate' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
 static ContainsTemplate e; // expected-error {{variable of type 'ContainsTemplate' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
 static Template<Normal> f;
 
 template<class T>
-class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { char mForceInstantiation[sizeof(T)]; }; // expected-error-re 5 {{Cannot instantiate 'Mover<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { // expected-error-re 8 {{Cannot instantiate 'Mover<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+  char mForceInstantiation[sizeof(T)];
+};
 class IndirectTemplatePointery : Template<Pointery> {}; // expected-note {{'IndirectTemplatePointery' is a non-memmove()able type because it inherits from a non-memmove()able type 'Template<Pointery>'}}
 class ContainsTemplatePointery { Template<Pointery> m; }; // expected-note {{'ContainsTemplatePointery' is a non-memmove()able type because member 'm' is a non-memmove()able type 'Template<Pointery>'}}
 
 static Mover<Template<Pointery>> n; // expected-note {{instantiation of 'Mover<Template<Pointery> >' requested here}}
 static Mover<Template<IndirectPointery>> o; // expected-note {{instantiation of 'Mover<Template<IndirectPointery> >' requested here}}
 static Mover<Template<ContainsPointery>> p; // expected-note {{instantiation of 'Mover<Template<ContainsPointery> >' requested here}}
 static Mover<IndirectTemplatePointery> q; // expected-note {{instantiation of 'Mover<IndirectTemplatePointery>' requested here}}
 static Mover<ContainsTemplatePointery> r; // expected-note {{instantiation of 'Mover<ContainsTemplatePointery>' requested here}}
 static Mover<Template<Normal>> s;
+
+template<class T, class... Ts>
+class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS ManyTs {}; // expected-note-re 3 {{'ManyTs<{{.*}}>' is a non-memmove()able type because it has a template argument non-memmove()able type '{{.*}}'}}
+
+static Mover<ManyTs<Pointery>> t; // expected-note {{instantiation of 'Mover<ManyTs<Pointery> >' requested here}}
+static Mover<ManyTs<Normal, Pointery>> u; // expected-note {{instantiation of 'Mover<ManyTs<Normal, Pointery> >' requested here}}
+static Mover<ManyTs<Normal, Normal, Pointery>> v; // expected-note {{instantiation of 'Mover<ManyTs<Normal, Normal, Pointery> >' requested here}}