Merge remote-tracking branch 'origin/swift-4.1-branch' into stable
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 4128155..798de28 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -51,7 +51,8 @@
       TerseOutput(false), PolishForDeclaration(false),
       Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
       IncludeNewlines(true), MSVCFormatting(false),
-      ConstantsAsWritten(false), UseStdFunctionForLambda(false) { }
+      ConstantsAsWritten(false), SuppressImplicitBase(false),
+      UseStdFunctionForLambda(false) { }
 
   /// \brief Adjust this printing policy for cases where it's known that
   /// we're printing C++ code (for instance, if AST dumping reaches a
@@ -222,7 +223,10 @@
   /// 0x10
   /// 2.5e3
   /// \endcode
-  bool ConstantsAsWritten;
+  bool ConstantsAsWritten : 1;
+
+  /// \brief When true, don't print the implicit 'self' or 'this' expressions.
+  bool SuppressImplicitBase : 1;
 
   /// \brief Whether we should use std::function<...> for lambda record types.
   bool UseStdFunctionForLambda : 1;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 239017d..210dabe 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -10178,8 +10178,7 @@
   void CodeCompleteObjCPropertyDefinition(Scope *S);
   void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
                                               IdentifierInfo *PropertyName);
-  void CodeCompleteObjCMethodDecl(Scope *S,
-                                  bool IsInstanceMethod,
+  void CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
                                   ParsedType ReturnType);
   void CodeCompleteObjCMethodDeclSelector(Scope *S,
                                           bool IsInstanceMethod,
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 89fd1b9..7e77d2b 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1324,10 +1324,25 @@
         OS, Node->template_arguments(), Policy);
 }
 
+static bool isImplicitSelf(const Expr *E) {
+  if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (const ImplicitParamDecl *PD =
+            dyn_cast<ImplicitParamDecl>(DRE->getDecl())) {
+      if (PD->getParameterKind() == ImplicitParamDecl::ObjCSelf &&
+          DRE->getLocStart().isInvalid())
+        return true;
+    }
+  }
+  return false;
+}
+
 void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
   if (Node->getBase()) {
-    PrintExpr(Node->getBase());
-    OS << (Node->isArrow() ? "->" : ".");
+    if (!Policy.SuppressImplicitBase ||
+        !isImplicitSelf(Node->getBase()->IgnoreImpCasts())) {
+      PrintExpr(Node->getBase());
+      OS << (Node->isArrow() ? "->" : ".");
+    }
   }
   OS << *Node->getDecl();
 }
@@ -1647,16 +1662,25 @@
   PrintCallArgs(Call);
   OS << ")";
 }
+
+static bool isImplicitThis(const Expr *E) {
+  if (const auto *TE = dyn_cast<CXXThisExpr>(E))
+    return TE->isImplicit();
+  return false;
+}
+
 void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
-  // FIXME: Suppress printing implicit bases (like "this")
-  PrintExpr(Node->getBase());
+  if (!Policy.SuppressImplicitBase || !isImplicitThis(Node->getBase())) {
+    PrintExpr(Node->getBase());
 
-  MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
-  FieldDecl  *ParentDecl   = ParentMember
-    ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : nullptr;
+    MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
+    FieldDecl *ParentDecl =
+        ParentMember ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl())
+                     : nullptr;
 
-  if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
-    OS << (Node->isArrow() ? "->" : ".");
+    if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
+      OS << (Node->isArrow() ? "->" : ".");
+  }
 
   if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl()))
     if (FD->isAnonymousStructOrUnion())
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index d2f70fc..89b7d0d 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -761,9 +761,15 @@
     SingleDecl = ParseObjCMethodDefinition();
     break;
   case tok::code_completion:
-      Actions.CodeCompleteOrdinaryName(getCurScope(), 
-                             CurParsedObjCImpl? Sema::PCC_ObjCImplementation
-                                              : Sema::PCC_Namespace);
+    if (CurParsedObjCImpl) {
+      // Code-complete Objective-C methods even without leading '-'/'+' prefix.
+      Actions.CodeCompleteObjCMethodDecl(getCurScope(),
+                                         /*IsInstanceMethod=*/None,
+                                         /*ReturnType=*/nullptr);
+    }
+    Actions.CodeCompleteOrdinaryName(
+        getCurScope(),
+        CurParsedObjCImpl ? Sema::PCC_ObjCImplementation : Sema::PCC_Namespace);
     cutOffParsing();
     return nullptr;
   case tok::kw_export:
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 700cf38..3620f60 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -6582,7 +6582,7 @@
 /// indexed by selector so they can be easily found.
 static void FindImplementableMethods(ASTContext &Context,
                                      ObjCContainerDecl *Container,
-                                     bool WantInstanceMethods,
+                                     Optional<bool> WantInstanceMethods,
                                      QualType ReturnType,
                                      KnownMethodsMap &KnownMethods,
                                      bool InOriginalClass = true) {
@@ -6653,7 +6653,7 @@
   // we want the methods from this container to override any methods
   // we've previously seen with the same selector.
   for (auto *M : Container->methods()) {
-    if (M->isInstanceMethod() == WantInstanceMethods) {
+    if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
       if (!ReturnType.isNull() &&
           !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
         continue;
@@ -7325,8 +7325,7 @@
   }
 }
 
-void Sema::CodeCompleteObjCMethodDecl(Scope *S, 
-                                      bool IsInstanceMethod,
+void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
                                       ParsedType ReturnTy) {
   // Determine the return type of the method we're declaring, if
   // provided.
@@ -7381,7 +7380,13 @@
     ObjCMethodDecl *Method = M->second.getPointer();
     CodeCompletionBuilder Builder(Results.getAllocator(),
                                   Results.getCodeCompletionTUInfo());
-    
+
+    // Add the '-'/'+' prefix if it wasn't provided yet.
+    if (!IsInstanceMethod) {
+      Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    }
+
     // If the result type was not already provided, add it to the
     // pattern as (type).
     if (ReturnType.isNull()) {
@@ -7483,11 +7488,13 @@
     if (IFace)
       for (auto *Cat : IFace->visible_categories())
         Containers.push_back(Cat);
-    
-    for (unsigned I = 0, N = Containers.size(); I != N; ++I)
-      for (auto *P : Containers[I]->instance_properties())
-        AddObjCKeyValueCompletions(P, IsInstanceMethod, ReturnType, Context, 
-                                   KnownSelectors, Results);
+
+    if (IsInstanceMethod) {
+      for (unsigned I = 0, N = Containers.size(); I != N; ++I)
+        for (auto *P : Containers[I]->instance_properties())
+          AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
+                                     KnownSelectors, Results);
+    }
   }
   
   Results.ExitScope();
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 856ddf6..5ad374b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -8880,10 +8880,10 @@
           diag::ext_function_specialization_in_class :
           diag::err_function_specialization_in_class)
           << NewFD->getDeclName();
-      } else if (CheckFunctionTemplateSpecialization(NewFD,
-                                  (HasExplicitTemplateArgs ? &TemplateArgs
-                                                           : nullptr),
-                                                     Previous))
+      } else if (!NewFD->isInvalidDecl() &&
+                 CheckFunctionTemplateSpecialization(
+                     NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
+                     Previous))
         NewFD->setInvalidDecl();
 
       // C++ [dcl.stc]p1:
diff --git a/lib/Tooling/Refactor/ExtractRepeatedExpressionIntoVariable.cpp b/lib/Tooling/Refactor/ExtractRepeatedExpressionIntoVariable.cpp
index dc90d9e..7e796b6 100644
--- a/lib/Tooling/Refactor/ExtractRepeatedExpressionIntoVariable.cpp
+++ b/lib/Tooling/Refactor/ExtractRepeatedExpressionIntoVariable.cpp
@@ -266,7 +266,10 @@
   PP.SuppressUnwrittenScope = true;
   T.print(OS, PP, /*PlaceHolder*/ Name);
   OS << " = ";
-  E->printPretty(OS, /*Helper=*/nullptr, Context.getPrintingPolicy());
+  PrintingPolicy ExprPP = Context.getPrintingPolicy();
+  ExprPP.SuppressStrongLifetime = true;
+  ExprPP.SuppressImplicitBase = true;
+  E->printPretty(OS, /*Helper=*/nullptr, ExprPP);
   OS << ";\n";
   Replacements.emplace_back(SourceRange(InsertionLoc, InsertionLoc), OS.str());
 
diff --git a/test/Index/complete-method-decls.m b/test/Index/complete-method-decls.m
index 8a17142..f561f81 100644
--- a/test/Index/complete-method-decls.m
+++ b/test/Index/complete-method-decls.m
@@ -236,3 +236,25 @@
 // RUN: c-index-test -code-completion-at=%s:107:2 %s -target x86_64-apple-macosx10.7 | FileCheck -check-prefix=CHECK-NULLABILITY2 %s
 // CHECK-NULLABILITY2: ObjCInstanceMethodDecl:{LeftParen (}{Text instancetype}{RightParen )}{TypedText getI3} (40)
 // CHECK-NULLABILITY2: ObjCInstanceMethodDecl:{LeftParen (}{Text I3 *}{RightParen )}{TypedText produceI3}{TypedText :}{LeftParen (}{Text I3 *}{RightParen )}{Text i3} (40)
+
+@interface CompleteWithoutLeadingPrefix
+
+- (void)aMethod;
++ (int)aClassMethod:(int)x;
+@property int p;
+
+@end
+
+@implementation CompleteWithoutLeadingPrefix
+
+
+
+@end
+
+// RUN: c-index-test -code-completion-at=%s:250:1 %s | FileCheck -check-prefix=CHECK-COMP-NO-PREFIX %s
+// CHECK-COMP-NO-PREFIX: NotImplemented:{TypedText @end} (40)
+// CHECK-COMP-NO-PREFIX: ObjCClassMethodDecl:{Text +}{HorizontalSpace  }{LeftParen (}{Text int}{RightParen )}{TypedText aClassMethod}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x} (40)
+// CHECK-COMP-NO-PREFIX: ObjCInstanceMethodDecl:{Text -}{HorizontalSpace  }{LeftParen (}{Text void}{RightParen )}{TypedText aMethod} (40)
+// CHECK-COMP-NO-PREFIX: ObjCInterfaceDecl:{TypedText I1}
+// CHECK-COMP-NO-PREFIX: ObjCInstanceMethodDecl:{Text -}{HorizontalSpace  }{LeftParen (}{Text int}{RightParen )}{TypedText p} (40)
+// CHECK-COMP-NO-PREFIX: ObjCInstanceMethodDecl:{Text -}{HorizontalSpace  }{LeftParen (}{Text void}{RightParen )}{TypedText setP}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text p} (40)
diff --git a/test/Refactor/ExtractRepeatedExpression/extract-repeated-expr-perform.cpp b/test/Refactor/ExtractRepeatedExpression/extract-repeated-expr-perform.cpp
index 4d8c400..f5ddc8a 100644
--- a/test/Refactor/ExtractRepeatedExpression/extract-repeated-expr-perform.cpp
+++ b/test/Refactor/ExtractRepeatedExpression/extract-repeated-expr-perform.cpp
@@ -98,3 +98,19 @@
 }
 
 // RUN: clang-refactor-test perform -action extract-repeated-expr-into-var -at=%s:94:5 %s | FileCheck --check-prefix=CHECK6 %s
+
+class ImplicitThisRewrite {
+  AWrapper &ref;
+  ImplicitThisRewrite(AWrapper &ref) : ref(ref) {}
+
+  void method() {
+    // implicit-this: +1:5  // IMPLICIT-THIS: "AClass &object = this->ref.object(1);\nobject" [[@LINE+1]]:5 -> [[@LINE+1]]:18
+    ref.object(1).method(); // IMPLICIT-NO-THIS: "AClass &object = ref.object(1);\nobject" [[@LINE]]:5 -> [[@LINE]]:18
+    ref.object(1).constMethod(); // IMPLICIT-THIS-ME: "object" [[@LINE]]:5 -> [[@LINE]]:18
+    // implicit-this2: +1:5
+    this->ref.object(1).method(); // IMPLICIT-THIS-MENEXT: "object" [[@LINE]]:5 -> [[@LINE]]:24
+  }
+};
+
+// RUN: clang-refactor-test perform -action extract-repeated-expr-into-var -at=implicit-this %s | FileCheck --check-prefixes=IMPLICIT-NO-THIS,IMPLICIT-THIS-ME %s
+// RUN: clang-refactor-test perform -action extract-repeated-expr-into-var -at=implicit-this2 %s | FileCheck --check-prefixes=IMPLICIT-THIS,IMPLICIT-THIS-ME %s
diff --git a/test/Refactor/ExtractRepeatedExpression/extract-repeated-expr-perform.m b/test/Refactor/ExtractRepeatedExpression/extract-repeated-expr-perform.m
index 23ed359..cc14c23 100644
--- a/test/Refactor/ExtractRepeatedExpression/extract-repeated-expr-perform.m
+++ b/test/Refactor/ExtractRepeatedExpression/extract-repeated-expr-perform.m
@@ -96,3 +96,24 @@
 
 // RUN: clang-refactor-test perform -action extract-repeated-expr-into-var -at=macro-arg1 %s | FileCheck --check-prefix=MACRO-ARG1 %s
 // RUN: clang-refactor-test perform -action extract-repeated-expr-into-var -at=macro-arg2 %s | FileCheck --check-prefix=MACRO-ARG2 %s
+
+@interface IVarSelf {
+  Wrapper *ref;
+}
+
+@end
+
+@implementation IVarSelf
+
+- (void)foo {
+  // ivar-self: +1:3         // IVAR-SELF: "Object *object = self->ref.object;\nobject" [[@LINE+1]]:3 -> [[@LINE+1]]:13
+  ref.object.prop = 0;       // IVAR-NO-SELF: "Object *object = ref.object;\nobject" [[@LINE]]:3 -> [[@LINE]]:13
+  ref.object->ivar = 1;      // IVAR: "object" [[@LINE]]:3 -> [[@LINE]]:13
+  // ivar-self2: +1:3
+  self->ref.object.prop = 2; // IVAR-NEXT: "object" [[@LINE]]:3 -> [[@LINE]]:19
+}
+
+@end
+
+// RUN: clang-refactor-test perform -action extract-repeated-expr-into-var -at=ivar-self %s | FileCheck --check-prefixes=IVAR-NO-SELF,IVAR %s
+// RUN: clang-refactor-test perform -action extract-repeated-expr-into-var -at=ivar-self2 %s | FileCheck --check-prefixes=IVAR-SELF,IVAR %s
diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp
index 74a2586..2c58fef 100644
--- a/test/SemaTemplate/deduction-crash.cpp
+++ b/test/SemaTemplate/deduction-crash.cpp
@@ -144,3 +144,20 @@
   template<typename T, typename U = void> int n<T *>; // expected-error +{{}} expected-note {{}}
   int k = n<void *>;
 }
+
+namespace deduceFunctionSpecializationForInvalidOutOfLineFunction {
+
+template <typename InputT, typename OutputT>
+struct SourceSelectionRequirement {
+  template<typename T>
+  OutputT evaluateSelectionRequirement(InputT &&Value) {
+  }
+};
+
+template <typename InputT, typename OutputT>
+OutputT SourceSelectionRequirement<InputT, OutputT>::
+evaluateSelectionRequirement<void>(InputT &&Value) { // expected-error {{cannot specialize a member of an unspecialized template}}
+  return Value;
+}
+
+}
diff --git a/test/SemaTemplate/explicit-specialization-member.cpp b/test/SemaTemplate/explicit-specialization-member.cpp
index c0c3680..e8165ac 100644
--- a/test/SemaTemplate/explicit-specialization-member.cpp
+++ b/test/SemaTemplate/explicit-specialization-member.cpp
@@ -38,24 +38,20 @@
 
   template<typename T>
   template<int N>
-  void Baz<T>::bar() { // expected-note {{couldn't infer template argument 'N'}}
+  void Baz<T>::bar() {
   }
 
-  // FIXME: We shouldn't try to match this against a prior declaration if
-  // template parameter matching failed.
   template<typename T>
-  void Baz<T>::bar<0>() { // expected-error {{cannot specialize a member of an unspecialized template}} \
-                          // expected-error {{no function template matches}}
+  void Baz<T>::bar<0>() { // expected-error {{cannot specialize a member of an unspecialized template}}
   }
 }
 
 namespace PR19340 {
 template<typename T> struct Helper {
-  template<int N> static void func(const T *m) {} // expected-note {{failed template argument deduction}}
+  template<int N> static void func(const T *m) {}
 };
 
-template<typename T> void Helper<T>::func<2>() {} // expected-error {{cannot specialize a member}} \
-                                                  // expected-error {{no function template matches}}
+template<typename T> void Helper<T>::func<2>() {} // expected-error {{cannot specialize a member}}
 }
 
 namespace SpecLoc {
diff --git a/unittests/AST/StmtPrinterTest.cpp b/unittests/AST/StmtPrinterTest.cpp
index 12b2032..a064440 100644
--- a/unittests/AST/StmtPrinterTest.cpp
+++ b/unittests/AST/StmtPrinterTest.cpp
@@ -31,18 +31,26 @@
 
 namespace {
 
-void PrintStmt(raw_ostream &Out, const ASTContext *Context, const Stmt *S) {
+using PolicyAdjusterType =
+    Optional<llvm::function_ref<void(PrintingPolicy &Policy)>>;
+
+void PrintStmt(raw_ostream &Out, const ASTContext *Context, const Stmt *S,
+               PolicyAdjusterType PolicyAdjuster) {
   assert(S != nullptr && "Expected non-null Stmt");
   PrintingPolicy Policy = Context->getPrintingPolicy();
+  if (PolicyAdjuster)
+    (*PolicyAdjuster)(Policy);
   S->printPretty(Out, /*Helper*/ nullptr, Policy);
 }
 
 class PrintMatch : public MatchFinder::MatchCallback {
   SmallString<1024> Printed;
   unsigned NumFoundStmts;
+  PolicyAdjusterType PolicyAdjuster;
 
 public:
-  PrintMatch() : NumFoundStmts(0) {}
+  PrintMatch(PolicyAdjusterType PolicyAdjuster)
+      : NumFoundStmts(0), PolicyAdjuster(PolicyAdjuster) {}
 
   void run(const MatchFinder::MatchResult &Result) override {
     const Stmt *S = Result.Nodes.getNodeAs<Stmt>("id");
@@ -53,7 +61,7 @@
       return;
 
     llvm::raw_svector_ostream Out(Printed);
-    PrintStmt(Out, Result.Context, S);
+    PrintStmt(Out, Result.Context, S, PolicyAdjuster);
   }
 
   StringRef getPrinted() const {
@@ -68,9 +76,10 @@
 template <typename T>
 ::testing::AssertionResult
 PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args,
-                   const T &NodeMatch, StringRef ExpectedPrinted) {
+                   const T &NodeMatch, StringRef ExpectedPrinted,
+                   PolicyAdjusterType PolicyAdjuster = None) {
 
-  PrintMatch Printer;
+  PrintMatch Printer(PolicyAdjuster);
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
   std::unique_ptr<FrontendActionFactory> Factory(
@@ -122,11 +131,13 @@
 
 ::testing::AssertionResult
 PrintedStmtCXX11Matches(StringRef Code, const StatementMatcher &NodeMatch,
-                        StringRef ExpectedPrinted) {
+                        StringRef ExpectedPrinted,
+                        PolicyAdjusterType PolicyAdjuster = None) {
   std::vector<std::string> Args;
   Args.push_back("-std=c++11");
   Args.push_back("-Wno-unused-value");
-  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
+  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
+                            PolicyAdjuster);
 }
 
 ::testing::AssertionResult PrintedStmtMSMatches(
@@ -146,6 +157,17 @@
                             ExpectedPrinted);
 }
 
+::testing::AssertionResult
+PrintedStmtObjCMatches(StringRef Code, const StatementMatcher &NodeMatch,
+                       StringRef ExpectedPrinted,
+                       PolicyAdjusterType PolicyAdjuster = None) {
+  std::vector<std::string> Args;
+  Args.push_back("-ObjC");
+  Args.push_back("-fobjc-runtime=macosx-10.12.0");
+  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
+                            PolicyAdjuster);
+}
+
 } // unnamed namespace
 
 TEST(StmtPrinter, TestIntegerLiteral) {
@@ -214,3 +236,41 @@
     "(a & b)"));
     // WRONG; Should be: (a & b).operator void *()
 }
+
+TEST(StmtPrinter, TestNoImplicitBases) {
+  const char *CPPSource = R"(
+class A {
+  int field;
+  int member() { return field; }
+};
+)";
+  // No implicit 'this'.
+  ASSERT_TRUE(PrintedStmtCXX11Matches(
+      CPPSource, memberExpr(anything()).bind("id"), "field",
+      PolicyAdjusterType(
+          [](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; })));
+  // Print implicit 'this'.
+  ASSERT_TRUE(PrintedStmtCXX11Matches(
+      CPPSource, memberExpr(anything()).bind("id"), "this->field"));
+
+  const char *ObjCSource = R"(
+@interface I {
+   int ivar;
+}
+@end
+@implementation I
+- (int) method {
+  return ivar;
+}
+@end
+      )";
+  // No implicit 'self'.
+  ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"),
+                                     "return ivar;\n",
+                                     PolicyAdjusterType([](PrintingPolicy &PP) {
+                                       PP.SuppressImplicitBase = true;
+                                     })));
+  // Print implicit 'self'.
+  ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"),
+                                     "return self->ivar;\n"));
+}