Bug 1254247 - Ignore implicit Expr wrappers due to temporary cleanup in MUST_USE analysis, r=ehsan
authorMichael Layzell <michael@thelayzells.com>
Fri, 11 Mar 2016 12:31:10 -0500
changeset 288342 79af3a479ce9229d2fd494466996acd11ec58be8
parent 288341 c3c4bc792bb542765f57869b00ccd8c28905e5ea
child 288343 a57d3b17dcf8a211f387a1d7015b577ca52cd6d7
push id73396
push usermichael@thelayzells.com
push dateFri, 11 Mar 2016 23:29:57 +0000
treeherdermozilla-inbound@79af3a479ce9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1254247
milestone48.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 1254247 - Ignore implicit Expr wrappers due to temporary cleanup in MUST_USE analysis, r=ehsan
build/clang-plugin/clang-plugin.cpp
build/clang-plugin/tests/TestMustUse.cpp
--- a/build/clang-plugin/clang-plugin.cpp
+++ b/build/clang-plugin/clang-plugin.cpp
@@ -383,16 +383,17 @@ public:
     }
 
     return false;
   }
 
   void HandleUnusedExprResult(const Stmt *stmt) {
     const Expr *E = dyn_cast_or_null<Expr>(stmt);
     if (E) {
+      E = E->IgnoreImplicit(); // Ignore ExprWithCleanup etc. implicit wrappers
       QualType T = E->getType();
       if (MustUse.hasEffectiveAnnotation(T) && !isIgnoredExprForMustUse(E)) {
         unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
             DiagnosticIDs::Error, "Unused value of must-use type %0");
 
         Diag.Report(E->getLocStart(), errorID) << T;
         MustUse.dumpAnnotationReason(Diag, T, E->getLocStart());
       }
--- a/build/clang-plugin/tests/TestMustUse.cpp
+++ b/build/clang-plugin/tests/TestMustUse.cpp
@@ -1,17 +1,22 @@
 #define MOZ_MUST_USE __attribute__((annotate("moz_must_use")))
 
+struct Temporary { ~Temporary(); };
 class MOZ_MUST_USE MustUse {};
 class MayUse {};
 
 MustUse producesMustUse();
 MustUse *producesMustUsePointer();
 MustUse &producesMustUseRef();
 
+MustUse producesMustUse(const Temporary& t);
+MustUse *producesMustUsePointer(const Temporary& t);
+MustUse &producesMustUseRef(const Temporary& t);
+
 MayUse producesMayUse();
 MayUse *producesMayUsePointer();
 MayUse &producesMayUseRef();
 
 void use(MustUse*);
 void use(MustUse&);
 void use(MustUse&&);
 void use(MayUse*);
@@ -24,154 +29,173 @@ void foo() {
 
   producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
   producesMustUsePointer();
   producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
   producesMayUse();
   producesMayUsePointer();
   producesMayUseRef();
   u = producesMustUse();
+  u = producesMustUse(Temporary());
   {
     producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMustUsePointer();
     producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMayUse();
     producesMayUsePointer();
     producesMayUseRef();
     u = producesMustUse();
+    u = producesMustUse(Temporary());
   }
   if (true) {
     producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMustUsePointer();
     producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMayUse();
     producesMayUsePointer();
     producesMayUseRef();
     u = producesMustUse();
+    u = producesMustUse(Temporary());
   } else {
     producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMustUsePointer();
     producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMayUse();
     producesMayUsePointer();
     producesMayUseRef();
     u = producesMustUse();
+    u = producesMustUse(Temporary());
   }
 
   if(true) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
   else producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
   if(true) producesMustUsePointer();
   else producesMustUsePointer();
   if(true) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
   else producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
   if(true) producesMayUse();
   else producesMayUse();
   if(true) producesMayUsePointer();
   else producesMayUsePointer();
   if(true) producesMayUseRef();
   else producesMayUseRef();
   if(true) u = producesMustUse();
   else u = producesMustUse();
+  if(true) u = producesMustUse(Temporary());
+  else u = producesMustUse(Temporary());
 
   while (true) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
   while (true) producesMustUsePointer();
   while (true) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
   while (true) producesMayUse();
   while (true) producesMayUsePointer();
   while (true) producesMayUseRef();
   while (true) u = producesMustUse();
+  while (true) u = producesMustUse(Temporary());
 
   do producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
   while (true);
   do producesMustUsePointer();
   while (true);
   do producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
   while (true);
   do producesMayUse();
   while (true);
   do producesMayUsePointer();
   while (true);
   do producesMayUseRef();
   while (true);
   do u = producesMustUse();
   while (true);
+  do u = producesMustUse(Temporary());
+  while (true);
 
   for (;;) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
   for (;;) producesMustUsePointer();
   for (;;) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
   for (;;) producesMayUse();
   for (;;) producesMayUsePointer();
   for (;;) producesMayUseRef();
   for (;;) u = producesMustUse();
+  for (;;) u = producesMustUse(Temporary());
 
   for (producesMustUse();;); // expected-error {{Unused value of must-use type 'MustUse'}}
   for (producesMustUsePointer();;);
   for (producesMustUseRef();;); // expected-error {{Unused value of must-use type 'MustUse'}}
   for (producesMayUse();;);
   for (producesMayUsePointer();;);
   for (producesMayUseRef();;);
   for (u = producesMustUse();;);
+  for (u = producesMustUse(Temporary());;);
 
   for (;;producesMustUse()); // expected-error {{Unused value of must-use type 'MustUse'}}
   for (;;producesMustUsePointer());
   for (;;producesMustUseRef()); // expected-error {{Unused value of must-use type 'MustUse'}}
   for (;;producesMayUse());
   for (;;producesMayUsePointer());
   for (;;producesMayUseRef());
   for (;;u = producesMustUse());
+  for (;;u = producesMustUse(Temporary()));
 
   use((producesMustUse(), false)); // expected-error {{Unused value of must-use type 'MustUse'}}
   use((producesMustUsePointer(), false));
   use((producesMustUseRef(), false)); // expected-error {{Unused value of must-use type 'MustUse'}}
   use((producesMayUse(), false));
   use((producesMayUsePointer(), false));
   use((producesMayUseRef(), false));
   use((u = producesMustUse(), false));
+  use((u = producesMustUse(Temporary()), false));
 
   switch (1) {
   case 1:
     producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMustUsePointer();
     producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMayUse();
     producesMayUsePointer();
     producesMayUseRef();
     u = producesMustUse();
+    u = producesMustUse(Temporary());
   case 2:
     producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
   case 3:
     producesMustUsePointer();
   case 4:
     producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
   case 5:
     producesMayUse();
   case 6:
     producesMayUsePointer();
   case 7:
     producesMayUseRef();
   case 8:
     u = producesMustUse();
+  case 9:
+    u = producesMustUse(Temporary());
   default:
     producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMustUsePointer();
     producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
     producesMayUse();
     producesMayUsePointer();
     producesMayUseRef();
     u = producesMustUse();
+    u = producesMustUse(Temporary());
   }
 
   use(producesMustUse());
   use(producesMustUsePointer());
   use(producesMustUseRef());
   use(producesMayUse());
   use(producesMayUsePointer());
   use(producesMayUseRef());
   use(u = producesMustUse());
+  use(u = producesMustUse(Temporary()));
 
   MustUse a = producesMustUse();
   MustUse *b = producesMustUsePointer();
   MustUse &c = producesMustUseRef();
   MayUse d = producesMayUse();
   MayUse *e = producesMayUsePointer();
   MayUse &f = producesMayUseRef();
   MustUse g = u = producesMustUse();
+  MustUse h = u = producesMustUse(Temporary());
 }