summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td2
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--clang/include/clang/Sema/Sema.h4
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp30
-rw-r--r--clang/test/Parser/MicrosoftExtensions.cpp4
-rw-r--r--clang/test/SemaCXX/MicrosoftExtensions.cpp7
6 files changed, 44 insertions, 6 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index dd3c22bf384..7a813b08a8b 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -147,6 +147,8 @@ def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
+def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">;
+
// Original name of this warning in Clang
def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bf9148e7d26..fe878725a81 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1691,6 +1691,9 @@ def override_keyword_hides_virtual_member_function : Error<
"%select{function|functions}1">;
def err_function_marked_override_not_overriding : Error<
"%0 marked 'override' but does not override any member functions">;
+def warn_function_marked_not_override_overriding : Warning <
+ "%0 overrides a member function but is not marked 'override'">,
+ InGroup<CXX11WarnOverrideMethod>;
def err_class_marked_final_used_as_base : Error<
"base %0 is marked '%select{final|sealed}1'">;
def warn_abstract_final_class : Warning<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ebcc4808b7c..811dab4345a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5138,6 +5138,10 @@ public:
/// CheckOverrideControl - Check C++11 override control semantics.
void CheckOverrideControl(NamedDecl *D);
+
+ /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
+ /// not used in the declaration of an overriding method.
+ void DiagnoseAbsenceOfOverrideControl(NamedDecl *D);
/// CheckForFunctionMarkedFinal - Checks whether a virtual member function
/// overrides a virtual member function marked 'final', according to
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 9adba66c41f..47a84927268 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1897,6 +1897,22 @@ void Sema::CheckOverrideControl(NamedDecl *D) {
<< MD->getDeclName();
}
+void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) {
+ if (D->isInvalidDecl() || D->hasAttr<OverrideAttr>())
+ return;
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
+ if (!MD || MD->isImplicit() || MD->hasAttr<FinalAttr>() ||
+ isa<CXXDestructorDecl>(MD))
+ return;
+
+ if (MD->size_overridden_methods() > 0) {
+ Diag(MD->getLocation(), diag::warn_function_marked_not_override_overriding)
+ << MD->getDeclName();
+ const CXXMethodDecl *OMD = *MD->begin_overridden_methods();
+ Diag(OMD->getLocation(), diag::note_overridden_virtual_function);
+ }
+}
+
/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member
/// function overrides a virtual member function marked 'final', according to
/// C++11 [class.virtual]p4.
@@ -4763,13 +4779,18 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ bool HasMethodWithOverrideControl = false,
+ HasOverridingMethodWithoutOverrideControl = false;
if (!Record->isDependentType()) {
for (auto *M : Record->methods()) {
// See if a method overloads virtual methods in a base
// class without overriding any.
if (!M->isStatic())
DiagnoseHiddenVirtualMethods(M);
-
+ if (M->hasAttr<OverrideAttr>())
+ HasMethodWithOverrideControl = true;
+ else if (M->size_overridden_methods() > 0)
+ HasOverridingMethodWithoutOverrideControl = true;
// Check whether the explicitly-defaulted special members are valid.
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
CheckExplicitlyDefaultedSpecialMember(M);
@@ -4788,6 +4809,13 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ if (HasMethodWithOverrideControl &&
+ HasOverridingMethodWithoutOverrideControl) {
+ // At least one method has the 'override' control declared.
+ // Diagnose all other overridden methods which do not have 'override' specified on them.
+ for (auto *M : Record->methods())
+ DiagnoseAbsenceOfOverrideControl(M);
+ }
// C++11 [dcl.constexpr]p8: A constexpr specifier for a non-static member
// function that is not a constructor declares that member function to be
// const. [...] The class of which that function is a member shall be
diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp
index ee530b8669f..85ccdc5490c 100644
--- a/clang/test/Parser/MicrosoftExtensions.cpp
+++ b/clang/test/Parser/MicrosoftExtensions.cpp
@@ -208,12 +208,12 @@ extern TypenameWrongPlace<AAAA> PR16925;
__interface MicrosoftInterface;
__interface MicrosoftInterface {
- void foo1() = 0;
+ void foo1() = 0; // expected-note {{overridden virtual function is here}}
virtual void foo2() = 0;
};
__interface MicrosoftDerivedInterface : public MicrosoftInterface {
- void foo1();
+ void foo1(); // expected-warning {{'foo1' overrides a member function but is not marked 'override'}}
void foo2() override;
void foo3();
};
diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp
index 6d221a409e7..ec3dfce52c1 100644
--- a/clang/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp
@@ -372,14 +372,15 @@ struct SomeBase {
// expected-note@+2 {{overridden virtual function is here}}
// expected-warning@+1 {{'sealed' keyword is a Microsoft extension}}
- virtual void SealedFunction() sealed;
+ virtual void SealedFunction() sealed; // expected-note {{overridden virtual function is here}}
};
// expected-note@+2 {{'SealedType' declared here}}
// expected-warning@+1 {{'sealed' keyword is a Microsoft extension}}
struct SealedType sealed : SomeBase {
- // expected-error@+1 {{declaration of 'SealedFunction' overrides a 'sealed' function}}
- virtual void SealedFunction();
+ // expected-error@+2 {{declaration of 'SealedFunction' overrides a 'sealed' function}}
+ // FIXME. warning can be suppressed if we're also issuing error for overriding a 'final' function.
+ virtual void SealedFunction(); // expected-warning {{'SealedFunction' overrides a member function but is not marked 'override'}}
// expected-warning@+1 {{'override' keyword is a C++11 extension}}
virtual void OverrideMe() override;
OpenPOWER on IntegriCloud