[PATCH] cpp11-migrate: Fix crash in AddOverride due to template instantiations (PR15827)

Guillaume Papin guillaume.papin at epitech.eu
Thu May 9 14:52:56 PDT 2013


  Fixes according to the review
  Thank you for your answer, my XFAIL example was bad as it matched the
  exact conditions I wanted to avoid adding the 'override' keyword.

Hi revane,

http://llvm-reviews.chandlerc.com/D769

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D769?vs=1889&id=1913#toc

Files:
  cpp11-migrate/AddOverride/AddOverrideActions.cpp
  test/cpp11-migrate/AddOverride/basic.cpp
  test/cpp11-migrate/AddOverride/pure_specifier_fail.cpp

Index: cpp11-migrate/AddOverride/AddOverrideActions.cpp
===================================================================
--- cpp11-migrate/AddOverride/AddOverrideActions.cpp
+++ cpp11-migrate/AddOverride/AddOverrideActions.cpp
@@ -32,28 +32,40 @@
   const CXXMethodDecl *M = Result.Nodes.getDeclAs<CXXMethodDecl>(MethodId);
   assert(M && "Bad Callback. No node provided");
 
+  if (!SM.isFromMainFile(M->getLocStart()))
+    return;
+
   // First check that there isn't already an override attribute.
-  if (!M->hasAttr<OverrideAttr>()) {
-    if (M->getLocStart().isFileID()) {
-      SourceLocation StartLoc;
-      if (M->hasInlineBody()) {
-        // Start at the beginning of the body and rewind back to the last
-        // non-whitespace character. We will insert the override keyword
-        // after that character.
-        // FIXME: This transform won't work if there is a comment between
-        // the end of the function prototype and the start of the body.
-        StartLoc = M->getBody()->getLocStart();
-        do {
-          StartLoc = StartLoc.getLocWithOffset(-1);
-        } while (isWhitespace(*FullSourceLoc(StartLoc, SM).getCharacterData()));
-        StartLoc = StartLoc.getLocWithOffset(1);
-      } else {
-        StartLoc = SM.getSpellingLoc(M->getLocEnd());
-        StartLoc = Lexer::getLocForEndOfToken(StartLoc, 0, SM, LangOptions());
-      }
-      Replace.insert(tooling::Replacement(SM, StartLoc, 0, " override"));
-      ++AcceptedChanges;
-    }
+  if (M->hasAttr<OverrideAttr>())
+    return;
+
+  // FIXME: Pure methods are not supported yet as it is difficult to track down
+  // the location of '= 0'.
+  if (M->isPure())
+    return;
+
+  if (const FunctionDecl *TemplateMethod = M->getTemplateInstantiationPattern())
+    M = cast<CXXMethodDecl>(TemplateMethod);
+
+  if (M->getParent()->hasAnyDependentBases())
+    return;
+
+  SourceLocation StartLoc;
+  if (M->hasInlineBody()) {
+    // Start at the beginning of the body and rewind back to the last
+    // non-whitespace character. We will insert the override keyword
+    // after that character.
+    // FIXME: This transform won't work if there is a comment between
+    // the end of the function prototype and the start of the body.
+    StartLoc = M->getBody()->getLocStart();
+    do {
+      StartLoc = StartLoc.getLocWithOffset(-1);
+    } while (isWhitespace(*FullSourceLoc(StartLoc, SM).getCharacterData()));
+    StartLoc = StartLoc.getLocWithOffset(1);
+  } else {
+    StartLoc = SM.getSpellingLoc(M->getLocEnd());
+    StartLoc = Lexer::getLocForEndOfToken(StartLoc, 0, SM, LangOptions());
   }
+  Replace.insert(tooling::Replacement(SM, StartLoc, 0, " override"));
+  ++AcceptedChanges;
 }
-
Index: test/cpp11-migrate/AddOverride/basic.cpp
===================================================================
--- test/cpp11-migrate/AddOverride/basic.cpp
+++ test/cpp11-migrate/AddOverride/basic.cpp
@@ -108,3 +108,41 @@
   // CHECK: void h() const LLVM_OVERRIDE;
 };
 
+// Test that override isn't added at the wrong place for "pure overrides"
+struct APure {
+  virtual APure *clone() = 0;
+};
+struct BPure : APure {
+  virtual BPure *clone() { return new BPure(); }
+};
+struct CPure : BPure {
+  virtual BPure *clone() = 0;
+  // CHECK: struct CPure : BPure {
+  // CHECK-NOT: virtual BPure *clone() = 0 override;
+  // CHECK: };
+};
+struct DPure : CPure {
+  virtual DPure *clone() { return new DPure(); }
+};
+
+// Test that override is not added on dangerous template constructs
+struct Base1 {
+  virtual void f();
+};
+struct Base2 {};
+template<typename T> struct Derived : T {
+  void f(); // adding 'override' here will break instantiation of Derived<Base2>
+  // CHECK: struct Derived
+  // CHECK: void f();
+};
+Derived<Base1> d1;
+Derived<Base2> d2;
+
+template <typename T>
+class M : public A {
+public:
+  virtual void i();
+  // CHECK: class M : public A {
+  // CHECK: virtual void i() override;
+};
+M<int> b;
Index: test/cpp11-migrate/AddOverride/pure_specifier_fail.cpp
===================================================================
--- /dev/null
+++ test/cpp11-migrate/AddOverride/pure_specifier_fail.cpp
@@ -0,0 +1,20 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -add-override %t.cpp -- -I %S
+// RUN: FileCheck -input-file=%t.cpp %s
+// XFAIL: *
+
+// Test that override isn't placed correctly after "pure overrides"
+struct A {
+  virtual A *clone() = 0;
+};
+struct B : A {
+  virtual B *clone() { return new B(); }
+};
+struct C : B {
+  virtual B *clone() = 0;
+  // CHECK: struct C : B {
+  // CHECK: virtual B *clone() override = 0;
+};
+struct D : C {
+  virtual D *clone() { return new D(); }
+};
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D769.2.patch
Type: text/x-patch
Size: 4690 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130509/54c5ceb1/attachment.bin>


More information about the cfe-commits mailing list