<div dir="ltr">Sorry for the delay. LGTM subject to a few comments:<div><br></div><div><div class="gmail_extra"><span style="color:rgb(0,0,0);font-family:'Courier New',Courier,monospace;font-size:14px;white-space:pre-wrap">+  if (HasMethodWithOverrideControl
+      && HasOverridingMethodWithoutOverrideControl) {
</span></div><div><span style="color:rgb(0,0,0);font-family:'Courier New',Courier,monospace;font-size:14px;white-space:pre-wrap"><br></span></div><div class="gmail_extra">The && should be on the previous line.</div><div class="gmail_extra"><br></div><div class="gmail_extra"><span style="color:rgb(0,0,0);font-family:'Courier New',Courier,monospace;font-size:14px;white-space:pre-wrap">+      if (!M->hasAttr<OverrideAttr>())
+        DiagnoseAbsenceOfOverrideControl(M);
</span></div><div><span style="color:rgb(0,0,0);font-family:'Courier New',Courier,monospace;font-size:14px;white-space:pre-wrap"><br></span></div><div class="gmail_extra">It seems strange to me to put the check for OverrideAttr here but put the check for FinalAttr and overridden functions and so on in DiagnoseAbsenceOfOverrideControl. Move this check into the function with the others?</div><div class="gmail_extra"><br></div><div class="gmail_extra"><span style="color:rgb(0,0,0);font-family:'Courier New',Courier,monospace;font-size:14px;white-space:pre-wrap">   // expected-error@+1 {{declaration of 'SealedFunction' overrides a 'sealed' function}}
-  virtual void SealedFunction();
+  virtual void SealedFunction(); // expected-warning {{'SealedFunction' overrides a member function but is not marked 'override'}}
</span></div><div><span style="color:rgb(0,0,0);font-family:'Courier New',Courier,monospace;font-size:14px;white-space:pre-wrap"><br></span></div><div class="gmail_extra">It would be nice to suppress the warning if we're also issuing an error for overriding a 'final' function. Please at least add a FIXME to the test for that so that someone fixing this later doesn't think this is deliberate.</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_quote">On Fri, Oct 10, 2014 at 11:01 AM, jahanian <span dir="ltr"><<a href="mailto:fjahanian@apple.com" target="_blank">fjahanian@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word">Here is a new patch for warning on missing ‘override’ with following changes from the old patch.<div><br></div><div>1. I have incorporated few refactoring suggested by you and others.</div><div>2. I removed ‘FixIt’ for now. It is not necessary for this patch and something we can incorporate</div><div>    later if this is something we want to do.</div><div>3. After reading all the discussions I no longer warn on missing ‘override’ on ‘final’ methods.</div><div>    I see the point made that it is redundant for ‘final’ which already means ‘override. And since it is in</div><div>    violation of coding guidelines, it is more likely to break code. I also understand</div><div>    that it is a contentious issue which may be changed later.</div><div>4. This patch warns if overriding method (without ‘override' keyword) is explicitly declared as ‘virtual’. </div><div>     I feel that this is a useful warning as ‘override’ keyword makes user’s intention verbose. But, I</div><div>     can be convinced otherwise. </div><div><br></div><div>     - Please review.</div><span class=""><font color="#888888"><div><br></div><div>- Fariborz</div><div><br></div><div><br></div><div>  </div></font></span></div><br><div style="word-wrap:break-word"><div><br><div><div>On Oct 2, 2014, at 5:24 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:</div><br><blockquote type="cite"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Oct 2, 2014 at 4:13 PM, Fariborz Jahanian <span dir="ltr"><<a href="mailto:fjahanian@apple.com" target="_blank">fjahanian@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: fjahanian<br>
Date: Thu Oct  2 18:13:51 2014<br>
New Revision: 218925<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=218925&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=218925&view=rev</a><br>
Log:<br>
Patch to warn if 'override' is missing<br>
for an overriding method if class has at least one<br>
'override' specified on one of its methods.<br>
Reviewed by Doug Gregor. <a>rdar://18295240</a><br>
(I have already checked in all llvm files with missing 'override'<br>
 methods and Bob Wilson has fixed a TableGen of FastISel so<br>
 no warnings are expected from build of llvm after this patch.<br>
 I have already verified this).<br>
<br>
Added:<br>
    cfe/trunk/test/FixIt/cxx11-fixit-missing-override.cpp<br>
    cfe/trunk/test/SemaCXX/cxx11-warn-missing-override.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
    cfe/trunk/test/CXX/class.derived/class.virtual/p3-0x.cpp<br>
    cfe/trunk/test/FixIt/fixit-cxx0x.cpp<br>
    cfe/trunk/test/Parser/MicrosoftExtensions.cpp<br>
    cfe/trunk/test/Parser/cxx0x-decl.cpp<br>
    cfe/trunk/test/Parser/cxx0x-in-cxx98.cpp<br>
    cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp<br>
    cfe/trunk/test/SemaCXX/attr-gnu.cpp<br>
    cfe/trunk/test/SemaCXX/cxx98-compat.cpp<br>
    cfe/trunk/test/SemaCXX/ms-interface.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Thu Oct  2 18:13:51 2014<br>
@@ -146,6 +146,8 @@ def CXX98CompatPedantic : DiagGroup<"c++<br>
<br>
 def CXX11Narrowing : DiagGroup<"c++11-narrowing">;<br>
<br>
+def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">;<br>
+<br>
 // Original name of this warning in Clang<br>
 def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>;<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Oct  2 18:13:51 2014<br>
@@ -1689,6 +1689,9 @@ def override_keyword_hides_virtual_membe<br>
   "%select{function|functions}1">;<br>
 def err_function_marked_override_not_overriding : Error<<br>
   "%0 marked 'override' but does not override any member functions">;<br>
+def warn_function_marked_not_override_overriding : Warning <<br>
+  "%0 overrides a member function but is not marked 'override'">,<br>
+  InGroup<CXX11WarnOverrideMethod>;<br>
 def err_class_marked_final_used_as_base : Error<<br>
   "base %0 is marked '%select{final|sealed}1'">;<br>
 def warn_abstract_final_class : Warning<<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Oct  2 18:13:51 2014<br>
@@ -5084,6 +5084,10 @@ public:<br>
<br>
   /// CheckOverrideControl - Check C++11 override control semantics.<br>
   void CheckOverrideControl(NamedDecl *D);<br>
+<br>
+  /// DiagnoseAbsenseOfOverrideControl - Diagnose if override control was<br>
+  /// not used in the; otherwise, overriding method.<br></blockquote><div><br></div><div>Something weird has happened to this comment.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+  void DiagnoseAbsenseOfOverrideControl(NamedDecl *D);<br>
<br>
   /// CheckForFunctionMarkedFinal - Checks whether a virtual member function<br>
   /// overrides a virtual member function marked 'final', according to<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Oct  2 18:13:51 2014<br>
@@ -1897,6 +1897,31 @@ void Sema::CheckOverrideControl(NamedDec<br>
       << MD->getDeclName();<br>
 }<br>
<br>
+void Sema::DiagnoseAbsenseOfOverrideControl(NamedDecl *D) {<br>
+  if (D->isInvalidDecl())<br>
+    return;<br>
+  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);<br>
+  if (!MD || MD->isImplicit() || isa<CXXDestructorDecl>(MD))<br>
+    return;<br></blockquote><div><br></div><div>Why do you skip destructors?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">+  bool HasOverriddenMethods =<br>
+    MD->begin_overridden_methods() != MD->end_overridden_methods();<br>
+  if (HasOverriddenMethods) {<br>
+    SourceLocation EndLocation =<br>
+      (MD->isPure() || MD->hasAttr<FinalAttr>())<br></blockquote><div><br></div><div>We should not warn if the function (or the class) has the 'final' attribute.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+        ? SourceLocation() : MD->getSourceRange().getEnd();<br>
+    Diag(MD->getLocation(), diag::warn_function_marked_not_override_overriding)<br>
+      << MD->getDeclName()<br>
+      << FixItHint::CreateReplacement(EndLocation, ") override");<br></blockquote><div><br></div><div>This fixit is not correct. The EndLocation isn't necessarily the location of the `)`, and the `override` does not necessarily go after the `)`. (Consider cv-qualifiers and ref-qualifiers, or functions whose return type includes trailing declarator chunks, or functions with trailing return types.)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+    for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),<br>
+         E = MD->end_overridden_methods(); I != E; ++I) {<br>
+      const CXXMethodDecl *OMD = *I;<br>
+      Diag(OMD->getLocation(), diag::note_overridden_virtual_function);<br>
+      break;<br>
+    }<br>
+  }<br>
+}<br>
+<br>
 /// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member<br>
 /// function overrides a virtual member function marked 'final', according to<br>
 /// C++11 [class.virtual]p4.<br>
@@ -4680,13 +4705,18 @@ void Sema::CheckCompletedCXXClass(CXXRec<br>
     }<br>
   }<br>
<br>
+  bool HasMethodWithOverrideControl = false,<br>
+       HasOverridingMethodWithoutOverrideControl = false;<br>
   if (!Record->isDependentType()) {<br>
     for (auto *M : Record->methods()) {<br>
       // See if a method overloads virtual methods in a base<br>
       // class without overriding any.<br>
       if (!M->isStatic())<br>
         DiagnoseHiddenVirtualMethods(M);<br>
-<br>
+      if (M->hasAttr<OverrideAttr>())<br>
+        HasMethodWithOverrideControl = true;<br>
+      else if (M->begin_overridden_methods() != M->end_overridden_methods())<br></blockquote><div><br></div><div>Maybe just use M->size_overridden_methods() here.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+        HasOverridingMethodWithoutOverrideControl = true;<br>
       // Check whether the explicitly-defaulted special members are valid.<br>
       if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())<br>
         CheckExplicitlyDefaultedSpecialMember(M);<br>
@@ -4705,6 +4735,14 @@ void Sema::CheckCompletedCXXClass(CXXRec<br>
     }<br>
   }<br>
<br>
+  if (HasMethodWithOverrideControl<br>
+      && HasOverridingMethodWithoutOverrideControl) {<br>
+    // At least one method has the 'override' control declared.<br>
+    // Diagnose all other overridden methods which do not have 'override' specified on them.<br>
+    for (auto *M : Record->methods())<br>
+      if (!M->hasAttr<OverrideAttr>())<br>
+        DiagnoseAbsenseOfOverrideControl(M);<br>
+  }<br>
   // C++11 [dcl.constexpr]p8: A constexpr specifier for a non-static member<br>
   // function that is not a constructor declares that member function to be<br>
   // const. [...] The class of which that function is a member shall be<br>
<br>
Modified: cfe/trunk/test/CXX/class.derived/class.virtual/p3-0x.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.derived/class.virtual/p3-0x.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.derived/class.virtual/p3-0x.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/class.derived/class.virtual/p3-0x.cpp (original)<br>
+++ cfe/trunk/test/CXX/class.derived/class.virtual/p3-0x.cpp Thu Oct  2 18:13:51 2014<br>
@@ -61,7 +61,7 @@ struct D : B {<br>
 namespace PR13499 {<br>
   struct X {<br>
     virtual void f();<br>
-    virtual void h();<br>
+    virtual void h(); // expected-note 2 {{overridden virtual function is here}}<br>
   };<br>
   template<typename T> struct A : X {<br>
     void f() override;<br>
@@ -83,7 +83,7 @@ namespace PR13499 {<br>
   template<typename...T> struct E : X {<br>
     void f(T...) override;<br>
     void g(T...) override; // expected-error {{only virtual member functions can be marked 'override'}}<br>
-    void h(T...) final;<br>
+    void h(T...) final; // expected-warning {{'h' overrides a member function but is not marked 'override'}}<br></blockquote><div><br></div><div>This warning is bogus; it makes no sense to require both 'override' and 'final'.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
     void i(T...) final; // expected-error {{only virtual member functions can be marked 'final'}}<br>
   };<br>
   // FIXME: Diagnose these in the template definition, not in the instantiation.<br>
@@ -91,13 +91,13 @@ namespace PR13499 {<br>
<br>
   template<typename T> struct Y : T {<br>
     void f() override;<br>
-    void h() final;<br>
+    void h() final; // expected-warning {{'h' overrides a member function but is not marked 'override'}}<br></blockquote><div><br></div><div>... likewise.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
   };<br>
   template<typename T> struct Z : T {<br>
     void g() override; // expected-error {{only virtual member functions can be marked 'override'}}<br>
     void i() final; // expected-error {{only virtual member functions can be marked 'final'}}<br>
   };<br>
-  Y<X> y;<br>
+  Y<X> y; // expected-note {{in instantiation of}}<br>
   Z<X> z; // expected-note {{in instantiation of}}<br>
 }<br>
<br>
<br>
Added: cfe/trunk/test/FixIt/cxx11-fixit-missing-override.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/cxx11-fixit-missing-override.cpp?rev=218925&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/cxx11-fixit-missing-override.cpp?rev=218925&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/FixIt/cxx11-fixit-missing-override.cpp (added)<br>
+++ cfe/trunk/test/FixIt/cxx11-fixit-missing-override.cpp Thu Oct  2 18:13:51 2014<br>
@@ -0,0 +1,33 @@<br>
+// RUN: cp %s %t<br>
+// RUN: %clang_cc1 -x c++ -std=c++11 -Winconsistent-missing-override -fixit %t<br>
+// RUN: %clang_cc1 -x c++ -std=c++11 -Winconsistent-missing-override -Werror %t<br>
+<br>
+struct A<br>
+{<br>
+    virtual void foo();<br>
+    virtual void bar(); // expected-note {{overridden virtual function is here}}<br>
+    virtual void gorf() {}<br>
+    virtual void g() = 0; // expected-note {{overridden virtual function is here}}<br>
+};<br>
+<br>
+struct B : A<br>
+{<br>
+    void foo() override;<br>
+    void bar(); // expected-warning {{'bar' overrides a member function but is not marked 'override'}}<br>
+};<br>
+<br>
+struct C : B<br>
+{<br>
+    virtual void g() override = 0;  // expected-warning {{'g' overrides a member function but is not marked 'override'}}<br>
+    virtual void gorf() override {}<br>
+    void foo() {}<br>
+};<br>
+<br>
+struct D : C {<br>
+  virtual void g()override ;<br>
+  virtual void foo(){<br>
+  }<br>
+  void bar() override;<br>
+};<br>
+<br>
+<br>
<br>
Modified: cfe/trunk/test/FixIt/fixit-cxx0x.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/FixIt/fixit-cxx0x.cpp (original)<br>
+++ cfe/trunk/test/FixIt/fixit-cxx0x.cpp Thu Oct  2 18:13:51 2014<br>
@@ -24,7 +24,7 @@ namespace SemiCommaTypo {<br>
   int o;<br>
<br>
   struct Base {<br>
-    virtual void f2(), f3();<br>
+    virtual void f2(), f3(); // expected-note {{overridden virtual function is here}}<br>
   };<br>
   struct MemberDeclarator : Base {<br>
     int k : 4,<br>
@@ -33,7 +33,7 @@ namespace SemiCommaTypo {<br>
     char c, // expected-error {{expected ';' at end of declaration}}<br>
     typedef void F(), // expected-error {{expected ';' at end of declaration}}<br>
     F f1,<br>
-      f2 final,<br>
+      f2 final, // expected-warning {{'f2' overrides a member function but is not marked 'override'}}<br>
       f3 override, // expected-error {{expected ';' at end of declaration}}<br>
   };<br>
 }<br>
<br>
Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original)<br>
+++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Thu Oct  2 18:13:51 2014<br>
@@ -208,12 +208,12 @@ extern TypenameWrongPlace<AAAA> PR16925;<br>
<br>
 __interface MicrosoftInterface;<br>
 __interface MicrosoftInterface {<br>
-   void foo1() = 0;<br>
+   void foo1() = 0; // expected-note {{overridden virtual function is here}}<br>
    virtual void foo2() = 0;<br>
 };<br>
<br>
 __interface MicrosoftDerivedInterface : public MicrosoftInterface {<br>
-  void foo1();<br>
+  void foo1(); // expected-warning {{'foo1' overrides a member function but is not marked 'override'}}<br>
   void foo2() override;<br>
   void foo3();<br>
 };<br>
<br>
Modified: cfe/trunk/test/Parser/cxx0x-decl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-decl.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-decl.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Parser/cxx0x-decl.cpp (original)<br>
+++ cfe/trunk/test/Parser/cxx0x-decl.cpp Thu Oct  2 18:13:51 2014<br>
@@ -83,13 +83,13 @@ namespace PR5066 {<br>
<br>
 namespace FinalOverride {<br>
   struct Base {<br>
-    virtual void *f();<br>
+    virtual void *f(); // expected-note {{overridden virtual function is here}}<br>
     virtual void *g();<br>
     virtual void *h();<br>
     virtual void *i();<br>
   };<br>
   struct Derived : Base {<br>
-    virtual auto f() -> void *final;<br>
+    virtual auto f() -> void *final; // expected-warning {{'f' overrides a member function but is not marked 'override'}}<br>
     virtual auto g() -> void *override;<br>
     virtual auto h() -> void *final override;<br>
     virtual auto i() -> void *override final;<br>
<br>
Modified: cfe/trunk/test/Parser/cxx0x-in-cxx98.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-in-cxx98.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-in-cxx98.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Parser/cxx0x-in-cxx98.cpp (original)<br>
+++ cfe/trunk/test/Parser/cxx0x-in-cxx98.cpp Thu Oct  2 18:13:51 2014<br>
@@ -10,11 +10,12 @@ struct X {<br>
<br>
 struct B {<br>
   virtual void f();<br>
-  virtual void g();<br>
+  virtual void g(); // expected-note {{overridden virtual function is here}}<br>
 };<br>
 struct D final : B { // expected-warning {{'final' keyword is a C++11 extension}}<br>
   virtual void f() override; // expected-warning {{'override' keyword is a C++11 extension}}<br>
-  virtual void g() final; // expected-warning {{'final' keyword is a C++11 extension}}<br>
+  virtual void g() final; // expected-warning {{'final' keyword is a C++11 extension}} \<br>
+                         // expected-warning {{'g' overrides a member function but is not marked 'override'}}<br>
 };<br>
<br>
 void NewBracedInitList() {<br>
<br>
Modified: cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp Thu Oct  2 18:13:51 2014<br>
@@ -372,14 +372,14 @@ struct SomeBase {<br>
<br>
   // expected-note@+2 {{overridden virtual function is here}}<br>
   // expected-warning@+1 {{'sealed' keyword is a Microsoft extension}}<br>
-  virtual void SealedFunction() sealed;<br>
+  virtual void SealedFunction() sealed; // expected-note {{overridden virtual function is here}}<br>
 };<br>
<br>
 // expected-note@+2 {{'SealedType' declared here}}<br>
 // expected-warning@+1 {{'sealed' keyword is a Microsoft extension}}<br>
 struct SealedType sealed : SomeBase {<br>
   // expected-error@+1 {{declaration of 'SealedFunction' overrides a 'sealed' function}}<br>
-  virtual void SealedFunction();<br>
+  virtual void SealedFunction(); // expected-warning {{'SealedFunction' overrides a member function but is not marked 'override'}}<br>
<br>
   // expected-warning@+1 {{'override' keyword is a C++11 extension}}<br>
   virtual void OverrideMe() override;<br>
<br>
Modified: cfe/trunk/test/SemaCXX/attr-gnu.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-gnu.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-gnu.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/attr-gnu.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/attr-gnu.cpp Thu Oct  2 18:13:51 2014<br>
@@ -15,14 +15,15 @@ void g(int a[static [[]] 5]); // expecte<br>
 namespace {<br>
 class B {<br>
 public:<br>
-  virtual void test() {}<br>
+  virtual void test() {} // expected-note {{overridden virtual function is here}}<br>
   virtual void test2() {}<br>
   virtual void test3() {}<br>
 };<br>
<br>
 class D : public B {<br>
 public:<br>
-  void test() __attribute__((deprecated)) final {} // expected-warning {{GCC does not allow an attribute in this position on a function declaration}}<br>
+  void test() __attribute__((deprecated)) final {} // expected-warning {{GCC does not allow an attribute in this position on a function declaration}} \<br>
+                                                  // expected-warning {{'test' overrides a member function but is not marked 'override'}}<br>
   void test2() [[]] override {} // Ok<br>
   void test3() __attribute__((cf_unknown_transfer)) override {} // Ok, not known to GCC.<br>
 };<br>
<br>
Added: cfe/trunk/test/SemaCXX/cxx11-warn-missing-override.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-warn-missing-override.cpp?rev=218925&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-warn-missing-override.cpp?rev=218925&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/cxx11-warn-missing-override.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/cxx11-warn-missing-override.cpp Thu Oct  2 18:13:51 2014<br>
@@ -0,0 +1,21 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -Winconsistent-missing-override -verify -std=c++11 %s<br>
+struct A<br>
+{<br>
+    virtual void foo();<br>
+    virtual void bar(); // expected-note {{overridden virtual function is here}}<br>
+    virtual void gorf() {}<br>
+    virtual void g() = 0; // expected-note {{overridden virtual function is here}}<br>
+};<br>
+<br>
+struct B : A<br>
+{<br>
+    void foo() override;<br>
+    void bar(); // expected-warning {{'bar' overrides a member function but is not marked 'override'}}<br>
+};<br>
+<br>
+struct C : B<br>
+{<br>
+    virtual void g() = 0;  // expected-warning {{'g' overrides a member function but is not marked 'override'}}<br>
+    virtual void gorf() override {}<br>
+};<br>
+<br>
<br>
Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Thu Oct  2 18:13:51 2014<br>
@@ -120,11 +120,12 @@ struct InClassInit {<br>
<br>
 struct OverrideControlBase {<br>
   virtual void f();<br>
-  virtual void g();<br>
+  virtual void g(); // expected-note {{overridden virtual function is here}}<br>
 };<br>
 struct OverrideControl final : OverrideControlBase { // expected-warning {{'final' keyword is incompatible with C++98}}<br>
   virtual void f() override; // expected-warning {{'override' keyword is incompatible with C++98}}<br>
-  virtual void g() final; // expected-warning {{'final' keyword is incompatible with C++98}}<br>
+  virtual void g() final; // expected-warning {{'final' keyword is incompatible with C++98}} \<br>
+                         // expected-warning {{'g' overrides a member function but is not marked 'override'}}<br>
 };<br>
<br>
 using AliasDecl = int; // expected-warning {{alias declarations are incompatible with C++98}}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/ms-interface.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-interface.cpp?rev=218925&r1=218924&r2=218925&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-interface.cpp?rev=218925&r1=218924&r2=218925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/ms-interface.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/ms-interface.cpp Thu Oct  2 18:13:51 2014<br>
@@ -12,7 +12,7 @@ __interface I1 {<br>
   operator int();<br>
   // expected-error@+1 {{nested class I1::(anonymous) is not permitted within an interface type}}<br>
   struct { int a; };<br>
-  void fn2() {<br>
+  void fn2() { // expected-note {{overridden virtual function is here}}<br>
     struct A { }; // should be ignored: not a nested class<br>
   }<br>
 protected: // expected-error {{interface types cannot specify 'protected' access}}<br>
@@ -44,7 +44,7 @@ __interface I3 final {<br>
 __interface I4 : I1, I2 {<br>
   void fn1() const override;<br>
   // expected-error@+1 {{'final' keyword not permitted with interface types}}<br>
-  void fn2() final;<br>
+  void fn2() final; // expected-warning {{'fn2' overrides a member function but is not marked 'override'}}<br>
 };<br>
<br>
 // expected-error@+1 {{interface type cannot inherit from non-public 'interface I1'}}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>
</blockquote></div><br></div></div>
<br></blockquote></div><br></div></div></div>