Hi rsmith,

Hi,

This patch adds a new diagnostic that checks for member function calls before 
all base classes in a mem-initializer-list are initialized, which is undefined 
behavior. (C++03 12.6.2p8; C++11 12.6.2p13.)

The added code looks for member call expressions which use implicit or explicit 
'this' inside of the arguments of a base class initializer to signal the 
warning.

http://reviews.llvm.org/D6561

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/member-call-before-bases-init.cpp
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1509,6 +1509,9 @@
 def note_uninit_in_this_constructor : Note<
   "during field initialization in %select{this|the implicit default}0 "
   "constructor">;
+def warn_member_call_before_bases_init : Warning<
+  "member function %0 called before all base classes were initialized">,
+  InGroup<Uninitialized>;
 def warn_static_self_reference_in_init : Warning<
   "static variable %0 is suspiciously used within its own initialization">,
   InGroup<UninitializedStaticSelfInit>;
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -2638,6 +2638,44 @@
   }
 } // namespace
 
+namespace {
+class DiagnoseMemberCallVisitor
+    : public RecursiveASTVisitor<DiagnoseMemberCallVisitor> {
+  Sema &S;
+
+public:
+  DiagnoseMemberCallVisitor(Sema &SemaRef) : S(SemaRef) {}
+
+  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+    const Expr *IA = E->getImplicitObjectArgument();
+    if (IA->isImplicitCXXThis() || isa<CXXThisExpr>(IA)) {
+      S.Diag(E->getExprLoc(), diag::warn_member_call_before_bases_init)
+          << E->getDirectCallee();
+    }
+    return true;
+  }
+};
+
+// Diagnoses method calls before all base classes are initialized in a
+// mem-initializer-list which is undefined behaviour.
+// Source: C++03 12.6.2p8; C++11 12.6.2p13.
+static void
+DiagnoseUndefinedMemberFunctionCalls(Sema &SemaRef,
+                                     const CXXConstructorDecl *Constructor) {
+  if (SemaRef.getDiagnostics().isIgnored(
+          diag::warn_member_call_before_bases_init, Constructor->getLocation()))
+    return;
+
+  DiagnoseMemberCallVisitor Visitor(SemaRef);
+  for (const auto *I : Constructor->inits()) {
+    if (!I->isBaseInitializer())
+      continue;
+    Expr *E = I->getInit();
+    Visitor.TraverseStmt(E);
+  }
+}
+} // namespace
+
 /// \brief Enter a new C++ default initializer scope. After calling this, the
 /// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if
 /// parsing or instantiating the initializer failed.
@@ -4242,6 +4280,7 @@
   SetCtorInitializers(Constructor, AnyErrors, MemInits);
 
   DiagnoseUninitializedFields(*this, Constructor);
+  DiagnoseUndefinedMemberFunctionCalls(*this, Constructor);
 }
 
 void
Index: test/SemaCXX/member-call-before-bases-init.cpp
===================================================================
--- test/SemaCXX/member-call-before-bases-init.cpp
+++ test/SemaCXX/member-call-before-bases-init.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -verify %s
+
+class A {
+public:
+  A(int);
+};
+
+int g(int);
+
+class B : public A {
+  int j;
+
+public:
+  int f();
+  B() : A(g(f())), // expected-warning{{member function 'f' called before all base classes were initialized}}
+        j(f()) {}  // no-warning
+
+  B(int) : A(this->f()), // expected-warning{{member function 'f' called before all base classes were initialized}}
+           j(0) {}
+};
+
+class C {
+public:
+  C(int);
+};
+
+class D : public B, C {
+  int i;
+
+public:
+  D() : C(g(f())), // expected-warning{{member function 'f' called before all base classes were initialized}}
+        i(f()) {}  // no-warning
+};
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to