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"));
+}