Browse Source

[Sema][NFCI] Don't allocate storage for the various CorrectionCandidateCallback unless we are going to do some typo correction

The various CorrectionCandidateCallbacks are currently heap-allocated
unconditionally. This was needed because of delayed typo correction.
However these allocations represent currently 15.4% of all allocations
(number of allocations) when parsing all of Boost (!), mostly because
of ParseCastExpression, ParseStatementOrDeclarationAfterAttrtibutes
and isCXXDeclarationSpecifier. Note that all of these callback objects
are small. Let's not do this.

Instead initially allocate the callback on the stack, and only do a
heap allocation if we are going to do some typo correction. Do this by:

1. Adding a clone function to each callback, which will do a polymorphic
   clone of the callback. This clone function is required to be implemented
   by every callback (of which there is a fair amount). Make sure this is
   the case by making it pure virtual.

2. Use this clone function when we are going to try to correct a typo.

This additionally cut the time of -fsyntax-only on all of Boost by 0.5%
(not that much, but still something). No functional changes intended.

Differential Revision: https://reviews.llvm.org/D58827

Reviewed By: rnk



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356925 91177308-0d34-0410-b5e6-96231b3b80d8
Bruno Ricci 6 years ago
parent
commit
62e8a2946b

+ 2 - 3
include/clang/Parse/Parser.h

@@ -789,9 +789,8 @@ private:
     /// Annotation was successful.
     /// Annotation was successful.
     ANK_Success
     ANK_Success
   };
   };
-  AnnotatedNameKind
-  TryAnnotateName(bool IsAddressOfOperand,
-                  std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr);
+  AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand,
+                                    CorrectionCandidateCallback *CCC = nullptr);
 
 
   /// Push a tok::annot_cxxscope token onto the token stream.
   /// Push a tok::annot_cxxscope token onto the token stream.
   void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation);
   void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation);

+ 10 - 10
include/clang/Sema/Sema.h

@@ -1914,11 +1914,11 @@ public:
   ///        expression.
   ///        expression.
   ///
   ///
   /// \param CCC The correction callback, if typo correction is desired.
   /// \param CCC The correction callback, if typo correction is desired.
-  NameClassification
-  ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name,
-               SourceLocation NameLoc, const Token &NextToken,
-               bool IsAddressOfOperand,
-               std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr);
+  NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS,
+                                  IdentifierInfo *&Name, SourceLocation NameLoc,
+                                  const Token &NextToken,
+                                  bool IsAddressOfOperand,
+                                  CorrectionCandidateCallback *CCC = nullptr);
 
 
   /// Describes the detailed kind of a template name. Used in diagnostics.
   /// Describes the detailed kind of a template name. Used in diagnostics.
   enum class TemplateNameKindForDiagnostics {
   enum class TemplateNameKindForDiagnostics {
@@ -3266,7 +3266,7 @@ private:
   makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo,
   makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo,
                              Sema::LookupNameKind LookupKind, Scope *S,
                              Sema::LookupNameKind LookupKind, Scope *S,
                              CXXScopeSpec *SS,
                              CXXScopeSpec *SS,
-                             std::unique_ptr<CorrectionCandidateCallback> CCC,
+                             CorrectionCandidateCallback &CCC,
                              DeclContext *MemberContext, bool EnteringContext,
                              DeclContext *MemberContext, bool EnteringContext,
                              const ObjCObjectPointerType *OPT,
                              const ObjCObjectPointerType *OPT,
                              bool ErrorRecovery);
                              bool ErrorRecovery);
@@ -3350,7 +3350,7 @@ public:
   TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
   TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
                              Sema::LookupNameKind LookupKind,
                              Sema::LookupNameKind LookupKind,
                              Scope *S, CXXScopeSpec *SS,
                              Scope *S, CXXScopeSpec *SS,
-                             std::unique_ptr<CorrectionCandidateCallback> CCC,
+                             CorrectionCandidateCallback &CCC,
                              CorrectTypoKind Mode,
                              CorrectTypoKind Mode,
                              DeclContext *MemberContext = nullptr,
                              DeclContext *MemberContext = nullptr,
                              bool EnteringContext = false,
                              bool EnteringContext = false,
@@ -3360,7 +3360,7 @@ public:
   TypoExpr *CorrectTypoDelayed(const DeclarationNameInfo &Typo,
   TypoExpr *CorrectTypoDelayed(const DeclarationNameInfo &Typo,
                                Sema::LookupNameKind LookupKind, Scope *S,
                                Sema::LookupNameKind LookupKind, Scope *S,
                                CXXScopeSpec *SS,
                                CXXScopeSpec *SS,
-                               std::unique_ptr<CorrectionCandidateCallback> CCC,
+                               CorrectionCandidateCallback &CCC,
                                TypoDiagnosticGenerator TDG,
                                TypoDiagnosticGenerator TDG,
                                TypoRecoveryCallback TRC, CorrectTypoKind Mode,
                                TypoRecoveryCallback TRC, CorrectTypoKind Mode,
                                DeclContext *MemberContext = nullptr,
                                DeclContext *MemberContext = nullptr,
@@ -4230,7 +4230,7 @@ public:
   ExprResult ActOnIdExpression(
   ExprResult ActOnIdExpression(
       Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
       Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
       UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
       UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
-      std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr,
+      CorrectionCandidateCallback *CCC = nullptr,
       bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
       bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
 
 
   void DecomposeUnqualifiedId(const UnqualifiedId &Id,
   void DecomposeUnqualifiedId(const UnqualifiedId &Id,
@@ -4240,7 +4240,7 @@ public:
 
 
   bool
   bool
   DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
   DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
-                      std::unique_ptr<CorrectionCandidateCallback> CCC,
+                      CorrectionCandidateCallback &CCC,
                       TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
                       TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
                       ArrayRef<Expr *> Args = None, TypoExpr **Out = nullptr);
                       ArrayRef<Expr *> Args = None, TypoExpr **Out = nullptr);
 
 

+ 29 - 2
include/clang/Sema/TypoCorrection.h

@@ -312,6 +312,13 @@ public:
                : InvalidDistance;
                : InvalidDistance;
   }
   }
 
 
+  /// Clone this CorrectionCandidateCallback. CorrectionCandidateCallbacks are
+  /// initially stack-allocated. However in case where delayed typo-correction
+  /// is done we need to move the callback to storage with a longer lifetime.
+  /// Every class deriving from CorrectionCandidateCallback must implement
+  /// this method.
+  virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0;
+
   void setTypoName(IdentifierInfo *II) { Typo = II; }
   void setTypoName(IdentifierInfo *II) { Typo = II; }
   void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }
   void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }
 
 
@@ -342,14 +349,28 @@ protected:
   NestedNameSpecifier *TypoNNS;
   NestedNameSpecifier *TypoNNS;
 };
 };
 
 
+class DefaultFilterCCC final : public CorrectionCandidateCallback {
+public:
+  explicit DefaultFilterCCC(IdentifierInfo *Typo = nullptr,
+                            NestedNameSpecifier *TypoNNS = nullptr)
+      : CorrectionCandidateCallback(Typo, TypoNNS) {}
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<DefaultFilterCCC>(*this);
+  }
+};
+
 /// Simple template class for restricting typo correction candidates
 /// Simple template class for restricting typo correction candidates
 /// to ones having a single Decl* of the given type.
 /// to ones having a single Decl* of the given type.
 template <class C>
 template <class C>
-class DeclFilterCCC : public CorrectionCandidateCallback {
+class DeclFilterCCC final : public CorrectionCandidateCallback {
 public:
 public:
   bool ValidateCandidate(const TypoCorrection &candidate) override {
   bool ValidateCandidate(const TypoCorrection &candidate) override {
     return candidate.getCorrectionDeclAs<C>();
     return candidate.getCorrectionDeclAs<C>();
   }
   }
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<DeclFilterCCC>(*this);
+  }
 };
 };
 
 
 // Callback class to limit the allowed keywords and to only accept typo
 // Callback class to limit the allowed keywords and to only accept typo
@@ -362,6 +383,9 @@ public:
                         MemberExpr *ME = nullptr);
                         MemberExpr *ME = nullptr);
 
 
   bool ValidateCandidate(const TypoCorrection &candidate) override;
   bool ValidateCandidate(const TypoCorrection &candidate) override;
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<FunctionCallFilterCCC>(*this);
+  }
 
 
 private:
 private:
   unsigned NumArgs;
   unsigned NumArgs;
@@ -371,7 +395,7 @@ private:
 };
 };
 
 
 // Callback class that effectively disabled typo correction
 // Callback class that effectively disabled typo correction
-class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
+class NoTypoCorrectionCCC final : public CorrectionCandidateCallback {
 public:
 public:
   NoTypoCorrectionCCC() {
   NoTypoCorrectionCCC() {
     WantTypeSpecifiers = false;
     WantTypeSpecifiers = false;
@@ -384,6 +408,9 @@ public:
   bool ValidateCandidate(const TypoCorrection &candidate) override {
   bool ValidateCandidate(const TypoCorrection &candidate) override {
     return false;
     return false;
   }
   }
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<NoTypoCorrectionCCC>(*this);
+  }
 };
 };
 
 
 } // namespace clang
 } // namespace clang

+ 1 - 1
lib/Parse/ParseDecl.cpp

@@ -2854,7 +2854,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
       IdentifierInfo *Name = AfterScope.getIdentifierInfo();
       IdentifierInfo *Name = AfterScope.getIdentifierInfo();
       Sema::NameClassification Classification = Actions.ClassifyName(
       Sema::NameClassification Classification = Actions.ClassifyName(
           getCurScope(), SS, Name, AfterScope.getLocation(), Next,
           getCurScope(), SS, Name, AfterScope.getLocation(), Next,
-          /*IsAddressOfOperand*/false);
+          /*IsAddressOfOperand=*/false, /*CCC=*/nullptr);
       switch (Classification.getKind()) {
       switch (Classification.getKind()) {
       case Sema::NC_Error:
       case Sema::NC_Error:
         SkipMalformedDecl();
         SkipMalformedDecl();

+ 14 - 8
lib/Parse/ParseExpr.cpp

@@ -543,7 +543,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
 }
 }
 
 
 namespace {
 namespace {
-class CastExpressionIdValidator : public CorrectionCandidateCallback {
+class CastExpressionIdValidator final : public CorrectionCandidateCallback {
  public:
  public:
   CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes)
   CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes)
       : NextToken(Next), AllowNonTypes(AllowNonTypes) {
       : NextToken(Next), AllowNonTypes(AllowNonTypes) {
@@ -572,6 +572,10 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
     return false;
     return false;
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<CastExpressionIdValidator>(*this);
+  }
+
  private:
  private:
   Token NextToken;
   Token NextToken;
   bool AllowNonTypes;
   bool AllowNonTypes;
@@ -1041,19 +1045,21 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
     CXXScopeSpec ScopeSpec;
     CXXScopeSpec ScopeSpec;
     SourceLocation TemplateKWLoc;
     SourceLocation TemplateKWLoc;
     Token Replacement;
     Token Replacement;
-    auto Validator = llvm::make_unique<CastExpressionIdValidator>(
-        Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
-    Validator->IsAddressOfOperand = isAddressOfOperand;
+    CastExpressionIdValidator Validator(
+        /*Next=*/Tok,
+        /*AllowTypes=*/isTypeCast != NotTypeCast,
+        /*AllowNonTypes=*/isTypeCast != IsTypeCast);
+    Validator.IsAddressOfOperand = isAddressOfOperand;
     if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) {
     if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) {
-      Validator->WantExpressionKeywords = false;
-      Validator->WantRemainingKeywords = false;
+      Validator.WantExpressionKeywords = false;
+      Validator.WantRemainingKeywords = false;
     } else {
     } else {
-      Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
+      Validator.WantRemainingKeywords = Tok.isNot(tok::r_paren);
     }
     }
     Name.setIdentifier(&II, ILoc);
     Name.setIdentifier(&II, ILoc);
     Res = Actions.ActOnIdExpression(
     Res = Actions.ActOnIdExpression(
         getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),
         getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),
-        isAddressOfOperand, std::move(Validator),
+        isAddressOfOperand, &Validator,
         /*IsInlineAsmIdentifier=*/false,
         /*IsInlineAsmIdentifier=*/false,
         Tok.is(tok::r_paren) ? nullptr : &Replacement);
         Tok.is(tok::r_paren) ? nullptr : &Replacement);
     if (!Res.isInvalid() && Res.isUnset()) {
     if (!Res.isInvalid() && Res.isUnset()) {

+ 1 - 1
lib/Parse/ParseExprCXX.cpp

@@ -563,7 +563,7 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe
 
 
   ExprResult E = Actions.ActOnIdExpression(
   ExprResult E = Actions.ActOnIdExpression(
       getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren),
       getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren),
-      isAddressOfOperand, nullptr, /*IsInlineAsmIdentifier=*/false,
+      isAddressOfOperand, /*CCC=*/nullptr, /*IsInlineAsmIdentifier=*/false,
       &Replacement);
       &Replacement);
   if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less))
   if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less))
     checkPotentialAngleBracket(E);
     checkPotentialAngleBracket(E);

+ 7 - 4
lib/Parse/ParseStmt.cpp

@@ -116,7 +116,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
 }
 }
 
 
 namespace {
 namespace {
-class StatementFilterCCC : public CorrectionCandidateCallback {
+class StatementFilterCCC final : public CorrectionCandidateCallback {
 public:
 public:
   StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
   StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
     WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square,
     WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square,
@@ -139,6 +139,10 @@ public:
     return CorrectionCandidateCallback::ValidateCandidate(candidate);
     return CorrectionCandidateCallback::ValidateCandidate(candidate);
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<StatementFilterCCC>(*this);
+  }
+
 private:
 private:
   Token NextToken;
   Token NextToken;
 };
 };
@@ -181,9 +185,8 @@ Retry:
     if (Next.isNot(tok::coloncolon)) {
     if (Next.isNot(tok::coloncolon)) {
       // Try to limit which sets of keywords should be included in typo
       // Try to limit which sets of keywords should be included in typo
       // correction based on what the next token is.
       // correction based on what the next token is.
-      if (TryAnnotateName(/*IsAddressOfOperand*/ false,
-                          llvm::make_unique<StatementFilterCCC>(Next)) ==
-          ANK_Error) {
+      StatementFilterCCC CCC(Next);
+      if (TryAnnotateName(/*IsAddressOfOperand*/ false, &CCC) == ANK_Error) {
         // Handle errors here by skipping up to the next semicolon or '}', and
         // Handle errors here by skipping up to the next semicolon or '}', and
         // eat the semicolon if that's what stopped us.
         // eat the semicolon if that's what stopped us.
         SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
         SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);

+ 7 - 3
lib/Parse/ParseTentative.cpp

@@ -1147,7 +1147,7 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
 }
 }
 
 
 namespace {
 namespace {
-class TentativeParseCCC : public CorrectionCandidateCallback {
+class TentativeParseCCC final : public CorrectionCandidateCallback {
 public:
 public:
   TentativeParseCCC(const Token &Next) {
   TentativeParseCCC(const Token &Next) {
     WantRemainingKeywords = false;
     WantRemainingKeywords = false;
@@ -1165,6 +1165,10 @@ public:
 
 
     return CorrectionCandidateCallback::ValidateCandidate(Candidate);
     return CorrectionCandidateCallback::ValidateCandidate(Candidate);
   }
   }
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<TentativeParseCCC>(*this);
+  }
 };
 };
 }
 }
 /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration
 /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration
@@ -1293,8 +1297,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
       // a parse error one way or another. In that case, tell the caller that
       // a parse error one way or another. In that case, tell the caller that
       // this is ambiguous. Typo-correct to type and expression keywords and
       // this is ambiguous. Typo-correct to type and expression keywords and
       // to types and identifiers, in order to try to recover from errors.
       // to types and identifiers, in order to try to recover from errors.
-      switch (TryAnnotateName(false /* no nested name specifier */,
-                              llvm::make_unique<TentativeParseCCC>(Next))) {
+      TentativeParseCCC CCC(Next);
+      switch (TryAnnotateName(false /* no nested name specifier */, &CCC)) {
       case ANK_Error:
       case ANK_Error:
         return TPResult::Error;
         return TPResult::Error;
       case ANK_TentativeDecl:
       case ANK_TentativeDecl:

+ 4 - 4
lib/Parse/Parser.cpp

@@ -1487,7 +1487,7 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) {
 ///        no typo correction will be performed.
 ///        no typo correction will be performed.
 Parser::AnnotatedNameKind
 Parser::AnnotatedNameKind
 Parser::TryAnnotateName(bool IsAddressOfOperand,
 Parser::TryAnnotateName(bool IsAddressOfOperand,
-                        std::unique_ptr<CorrectionCandidateCallback> CCC) {
+                        CorrectionCandidateCallback *CCC) {
   assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope));
   assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope));
 
 
   const bool EnteringContext = false;
   const bool EnteringContext = false;
@@ -1523,9 +1523,9 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
   // after a scope specifier, because in general we can't recover from typos
   // after a scope specifier, because in general we can't recover from typos
   // there (eg, after correcting 'A::template B<X>::C' [sic], we would need to
   // there (eg, after correcting 'A::template B<X>::C' [sic], we would need to
   // jump back into scope specifier parsing).
   // jump back into scope specifier parsing).
-  Sema::NameClassification Classification = Actions.ClassifyName(
-      getCurScope(), SS, Name, NameLoc, Next, IsAddressOfOperand,
-      SS.isEmpty() ? std::move(CCC) : nullptr);
+  Sema::NameClassification Classification =
+      Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next,
+                           IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr);
 
 
   switch (Classification.getKind()) {
   switch (Classification.getKind()) {
   case Sema::NC_Error:
   case Sema::NC_Error:

+ 9 - 4
lib/Sema/SemaCXXScopeSpec.cpp

@@ -429,8 +429,9 @@ namespace {
 
 
 // Callback to only accept typo corrections that can be a valid C++ member
 // Callback to only accept typo corrections that can be a valid C++ member
 // intializer: either a non-static field member or a base class.
 // intializer: either a non-static field member or a base class.
-class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
- public:
+class NestedNameSpecifierValidatorCCC final
+    : public CorrectionCandidateCallback {
+public:
   explicit NestedNameSpecifierValidatorCCC(Sema &SRef)
   explicit NestedNameSpecifierValidatorCCC(Sema &SRef)
       : SRef(SRef) {}
       : SRef(SRef) {}
 
 
@@ -438,6 +439,10 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
     return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl());
     return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl());
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<NestedNameSpecifierValidatorCCC>(*this);
+  }
+
  private:
  private:
   Sema &SRef;
   Sema &SRef;
 };
 };
@@ -614,9 +619,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
     // different kind of error, so look for typos.
     // different kind of error, so look for typos.
     DeclarationName Name = Found.getLookupName();
     DeclarationName Name = Found.getLookupName();
     Found.clear();
     Found.clear();
+    NestedNameSpecifierValidatorCCC CCC(*this);
     if (TypoCorrection Corrected = CorrectTypo(
     if (TypoCorrection Corrected = CorrectTypo(
-            Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS,
-            llvm::make_unique<NestedNameSpecifierValidatorCCC>(*this),
+            Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, CCC,
             CTK_ErrorRecovery, LookupCtx, EnteringContext)) {
             CTK_ErrorRecovery, LookupCtx, EnteringContext)) {
       if (LookupCtx) {
       if (LookupCtx) {
         bool DroppedSpecifier =
         bool DroppedSpecifier =

+ 3 - 2
lib/Sema/SemaCodeComplete.cpp

@@ -6407,8 +6407,9 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
       SourceLocation TemplateKWLoc;
       SourceLocation TemplateKWLoc;
       UnqualifiedId id;
       UnqualifiedId id;
       id.setIdentifier(Super, SuperLoc);
       id.setIdentifier(Super, SuperLoc);
-      ExprResult SuperExpr =
-          ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false);
+      ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
+                                               /*HasTrailingLParen=*/false,
+                                               /*IsAddressOfOperand=*/false);
       return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
       return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
                                              SelIdents, AtArgumentExpression);
                                              SelIdents, AtArgumentExpression);
     }
     }

+ 34 - 28
lib/Sema/SemaDecl.cpp

@@ -61,7 +61,7 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) {
 
 
 namespace {
 namespace {
 
 
-class TypeNameValidatorCCC : public CorrectionCandidateCallback {
+class TypeNameValidatorCCC final : public CorrectionCandidateCallback {
  public:
  public:
    TypeNameValidatorCCC(bool AllowInvalid, bool WantClass = false,
    TypeNameValidatorCCC(bool AllowInvalid, bool WantClass = false,
                         bool AllowTemplates = false,
                         bool AllowTemplates = false,
@@ -105,6 +105,10 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback {
     return !WantClassName && candidate.isKeyword();
     return !WantClassName && candidate.isKeyword();
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<TypeNameValidatorCCC>(*this);
+  }
+
  private:
  private:
   bool AllowInvalidDecl;
   bool AllowInvalidDecl;
   bool WantClassName;
   bool WantClassName;
@@ -367,11 +371,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
   case LookupResult::NotFound:
   case LookupResult::NotFound:
   case LookupResult::NotFoundInCurrentInstantiation:
   case LookupResult::NotFoundInCurrentInstantiation:
     if (CorrectedII) {
     if (CorrectedII) {
-      TypoCorrection Correction =
-          CorrectTypo(Result.getLookupNameInfo(), Kind, S, SS,
-                      llvm::make_unique<TypeNameValidatorCCC>(
-                          true, isClassName, AllowDeducedTemplate),
-                      CTK_ErrorRecovery);
+      TypeNameValidatorCCC CCC(/*AllowInvalid=*/true, isClassName,
+                               AllowDeducedTemplate);
+      TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(), Kind,
+                                              S, SS, CCC, CTK_ErrorRecovery);
       IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
       IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
       TemplateTy Template;
       TemplateTy Template;
       bool MemberOfUnknownSpecialization;
       bool MemberOfUnknownSpecialization;
@@ -664,11 +667,12 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
 
 
   // There may have been a typo in the name of the type. Look up typo
   // There may have been a typo in the name of the type. Look up typo
   // results, in case we have something that we can suggest.
   // results, in case we have something that we can suggest.
+  TypeNameValidatorCCC CCC(/*AllowInvalid=*/false, /*WantClass=*/false,
+                           /*AllowTemplates=*/IsTemplateName,
+                           /*AllowNonTemplates=*/!IsTemplateName);
   if (TypoCorrection Corrected =
   if (TypoCorrection Corrected =
           CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS,
           CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS,
-                      llvm::make_unique<TypeNameValidatorCCC>(
-                          false, false, IsTemplateName, !IsTemplateName),
-                      CTK_ErrorRecovery)) {
+                      CCC, CTK_ErrorRecovery)) {
     // FIXME: Support error recovery for the template-name case.
     // FIXME: Support error recovery for the template-name case.
     bool CanRecover = !IsTemplateName;
     bool CanRecover = !IsTemplateName;
     if (Corrected.isKeyword()) {
     if (Corrected.isKeyword()) {
@@ -843,8 +847,7 @@ static ParsedType buildNestedType(Sema &S, CXXScopeSpec &SS,
 Sema::NameClassification
 Sema::NameClassification
 Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name,
 Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name,
                    SourceLocation NameLoc, const Token &NextToken,
                    SourceLocation NameLoc, const Token &NextToken,
-                   bool IsAddressOfOperand,
-                   std::unique_ptr<CorrectionCandidateCallback> CCC) {
+                   bool IsAddressOfOperand, CorrectionCandidateCallback *CCC) {
   DeclarationNameInfo NameInfo(Name, NameLoc);
   DeclarationNameInfo NameInfo(Name, NameLoc);
   ObjCMethodDecl *CurMethod = getCurMethodDecl();
   ObjCMethodDecl *CurMethod = getCurMethodDecl();
 
 
@@ -926,10 +929,9 @@ Corrected:
     // close to this name.
     // close to this name.
     if (!SecondTry && CCC) {
     if (!SecondTry && CCC) {
       SecondTry = true;
       SecondTry = true;
-      if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
-                                                 Result.getLookupKind(), S,
-                                                 &SS, std::move(CCC),
-                                                 CTK_ErrorRecovery)) {
+      if (TypoCorrection Corrected =
+              CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S,
+                          &SS, *CCC, CTK_ErrorRecovery)) {
         unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
         unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
         unsigned QualifiedDiag = diag::err_no_member_suggest;
         unsigned QualifiedDiag = diag::err_no_member_suggest;
 
 
@@ -1865,10 +1867,10 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
   if (!IDecl && DoTypoCorrection) {
   if (!IDecl && DoTypoCorrection) {
     // Perform typo correction at the given location, but only if we
     // Perform typo correction at the given location, but only if we
     // find an Objective-C class name.
     // find an Objective-C class name.
-    if (TypoCorrection C = CorrectTypo(
-            DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, TUScope, nullptr,
-            llvm::make_unique<DeclFilterCCC<ObjCInterfaceDecl>>(),
-            CTK_ErrorRecovery)) {
+    DeclFilterCCC<ObjCInterfaceDecl> CCC{};
+    if (TypoCorrection C =
+            CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName,
+                        TUScope, nullptr, CCC, CTK_ErrorRecovery)) {
       diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);
       diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);
       IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
       IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
       Id = IDecl->getIdentifier();
       Id = IDecl->getIdentifier();
@@ -7688,7 +7690,7 @@ namespace {
 
 
 // Callback to only accept typo corrections that have a non-zero edit distance.
 // Callback to only accept typo corrections that have a non-zero edit distance.
 // Also only accept corrections that have the same parent decl.
 // Also only accept corrections that have the same parent decl.
-class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
+class DifferentNameValidatorCCC final : public CorrectionCandidateCallback {
  public:
  public:
   DifferentNameValidatorCCC(ASTContext &Context, FunctionDecl *TypoFD,
   DifferentNameValidatorCCC(ASTContext &Context, FunctionDecl *TypoFD,
                             CXXRecordDecl *Parent)
                             CXXRecordDecl *Parent)
@@ -7720,6 +7722,10 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
     return false;
     return false;
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<DifferentNameValidatorCCC>(*this);
+  }
+
  private:
  private:
   ASTContext &Context;
   ASTContext &Context;
   FunctionDecl *OriginalFD;
   FunctionDecl *OriginalFD;
@@ -7767,6 +7773,8 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
   assert(!Prev.isAmbiguous() &&
   assert(!Prev.isAmbiguous() &&
          "Cannot have an ambiguity in previous-declaration lookup");
          "Cannot have an ambiguity in previous-declaration lookup");
   CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
   CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+  DifferentNameValidatorCCC CCC(SemaRef.Context, NewFD,
+                                MD ? MD->getParent() : nullptr);
   if (!Prev.empty()) {
   if (!Prev.empty()) {
     for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
     for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
          Func != FuncEnd; ++Func) {
          Func != FuncEnd; ++Func) {
@@ -7783,10 +7791,8 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
   // If the qualified name lookup yielded nothing, try typo correction
   // If the qualified name lookup yielded nothing, try typo correction
   } else if ((Correction = SemaRef.CorrectTypo(
   } else if ((Correction = SemaRef.CorrectTypo(
                   Prev.getLookupNameInfo(), Prev.getLookupKind(), S,
                   Prev.getLookupNameInfo(), Prev.getLookupKind(), S,
-                  &ExtraArgs.D.getCXXScopeSpec(),
-                  llvm::make_unique<DifferentNameValidatorCCC>(
-                      SemaRef.Context, NewFD, MD ? MD->getParent() : nullptr),
-                  Sema::CTK_ErrorRecovery, IsLocalFriend ? nullptr : NewDC))) {
+                  &ExtraArgs.D.getCXXScopeSpec(), CCC, Sema::CTK_ErrorRecovery,
+                  IsLocalFriend ? nullptr : NewDC))) {
     // Set up everything for the call to ActOnFunctionDeclarator
     // Set up everything for the call to ActOnFunctionDeclarator
     ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(),
     ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(),
                               ExtraArgs.D.getIdentifierLoc());
                               ExtraArgs.D.getIdentifierLoc());
@@ -13538,10 +13544,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
   // function declaration is going to be treated as an error.
   // function declaration is going to be treated as an error.
   if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) {
   if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) {
     TypoCorrection Corrected;
     TypoCorrection Corrected;
-    if (S &&
-        (Corrected = CorrectTypo(
-             DeclarationNameInfo(&II, Loc), LookupOrdinaryName, S, nullptr,
-             llvm::make_unique<DeclFilterCCC<FunctionDecl>>(), CTK_NonError)))
+    DeclFilterCCC<FunctionDecl> CCC{};
+    if (S && (Corrected =
+                  CorrectTypo(DeclarationNameInfo(&II, Loc), LookupOrdinaryName,
+                              S, nullptr, CCC, CTK_NonError)))
       diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion),
       diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion),
                    /*ErrorRecovery*/false);
                    /*ErrorRecovery*/false);
   }
   }

+ 25 - 15
lib/Sema/SemaDeclCXX.cpp

@@ -3781,7 +3781,7 @@ namespace {
 
 
 // Callback to only accept typo corrections that can be a valid C++ member
 // Callback to only accept typo corrections that can be a valid C++ member
 // intializer: either a non-static field member or a base class.
 // intializer: either a non-static field member or a base class.
-class MemInitializerValidatorCCC : public CorrectionCandidateCallback {
+class MemInitializerValidatorCCC final : public CorrectionCandidateCallback {
 public:
 public:
   explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
   explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
       : ClassDecl(ClassDecl) {}
       : ClassDecl(ClassDecl) {}
@@ -3795,6 +3795,10 @@ public:
     return false;
     return false;
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<MemInitializerValidatorCCC>(*this);
+  }
+
 private:
 private:
   CXXRecordDecl *ClassDecl;
   CXXRecordDecl *ClassDecl;
 };
 };
@@ -3924,11 +3928,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
 
 
       // If no results were found, try to correct typos.
       // If no results were found, try to correct typos.
       TypoCorrection Corr;
       TypoCorrection Corr;
+      MemInitializerValidatorCCC CCC(ClassDecl);
       if (R.empty() && BaseType.isNull() &&
       if (R.empty() && BaseType.isNull() &&
-          (Corr = CorrectTypo(
-               R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
-               llvm::make_unique<MemInitializerValidatorCCC>(ClassDecl),
-               CTK_ErrorRecovery, ClassDecl))) {
+          (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
+                              CCC, CTK_ErrorRecovery, ClassDecl))) {
         if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
         if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
           // We have found a non-static data member with a similar
           // We have found a non-static data member with a similar
           // name to what was typed; complain and initialize that
           // name to what was typed; complain and initialize that
@@ -9353,13 +9356,17 @@ static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
 namespace {
 namespace {
 
 
 // Callback to only accept typo corrections that are namespaces.
 // Callback to only accept typo corrections that are namespaces.
-class NamespaceValidatorCCC : public CorrectionCandidateCallback {
+class NamespaceValidatorCCC final : public CorrectionCandidateCallback {
 public:
 public:
   bool ValidateCandidate(const TypoCorrection &candidate) override {
   bool ValidateCandidate(const TypoCorrection &candidate) override {
     if (NamedDecl *ND = candidate.getCorrectionDecl())
     if (NamedDecl *ND = candidate.getCorrectionDecl())
       return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
       return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
     return false;
     return false;
   }
   }
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<NamespaceValidatorCCC>(*this);
+  }
 };
 };
 
 
 }
 }
@@ -9369,9 +9376,9 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
                                        SourceLocation IdentLoc,
                                        SourceLocation IdentLoc,
                                        IdentifierInfo *Ident) {
                                        IdentifierInfo *Ident) {
   R.clear();
   R.clear();
+  NamespaceValidatorCCC CCC{};
   if (TypoCorrection Corrected =
   if (TypoCorrection Corrected =
-          S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS,
-                        llvm::make_unique<NamespaceValidatorCCC>(),
+          S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS, CCC,
                         Sema::CTK_ErrorRecovery)) {
                         Sema::CTK_ErrorRecovery)) {
     if (DeclContext *DC = S.computeDeclContext(SS, false)) {
     if (DeclContext *DC = S.computeDeclContext(SS, false)) {
       std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
       std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
@@ -9866,7 +9873,7 @@ static CXXBaseSpecifier *findDirectBaseWithType(CXXRecordDecl *Derived,
 }
 }
 
 
 namespace {
 namespace {
-class UsingValidatorCCC : public CorrectionCandidateCallback {
+class UsingValidatorCCC final : public CorrectionCandidateCallback {
 public:
 public:
   UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
   UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
                     NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf)
                     NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf)
@@ -9936,6 +9943,10 @@ public:
     return !HasTypenameKeyword;
     return !HasTypenameKeyword;
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<UsingValidatorCCC>(*this);
+  }
+
 private:
 private:
   bool HasTypenameKeyword;
   bool HasTypenameKeyword;
   bool IsInstantiation;
   bool IsInstantiation;
@@ -10092,12 +10103,11 @@ NamedDecl *Sema::BuildUsingDeclaration(
         isa<TranslationUnitDecl>(LookupContext) &&
         isa<TranslationUnitDecl>(LookupContext) &&
         getSourceManager().isInSystemHeader(UsingLoc))
         getSourceManager().isInSystemHeader(UsingLoc))
       return nullptr;
       return nullptr;
-    if (TypoCorrection Corrected = CorrectTypo(
-            R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
-            llvm::make_unique<UsingValidatorCCC>(
-                HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
-                dyn_cast<CXXRecordDecl>(CurContext)),
-            CTK_ErrorRecovery)) {
+    UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
+                          dyn_cast<CXXRecordDecl>(CurContext));
+    if (TypoCorrection Corrected =
+            CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC,
+                        CTK_ErrorRecovery)) {
       // We reject candidates where DroppedSpecifier == true, hence the
       // We reject candidates where DroppedSpecifier == true, hence the
       // literal '0' below.
       // literal '0' below.
       diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
       diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)

+ 25 - 19
lib/Sema/SemaDeclObjC.cpp

@@ -499,7 +499,7 @@ namespace {
 // Callback to only accept typo corrections that are Objective-C classes.
 // Callback to only accept typo corrections that are Objective-C classes.
 // If an ObjCInterfaceDecl* is given to the constructor, then the validation
 // If an ObjCInterfaceDecl* is given to the constructor, then the validation
 // function will reject corrections to that class.
 // function will reject corrections to that class.
-class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
+class ObjCInterfaceValidatorCCC final : public CorrectionCandidateCallback {
  public:
  public:
   ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {}
   ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {}
   explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
   explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
@@ -510,6 +510,10 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
     return ID && !declaresSameEntity(ID, CurrentIDecl);
     return ID && !declaresSameEntity(ID, CurrentIDecl);
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<ObjCInterfaceValidatorCCC>(*this);
+  }
+
  private:
  private:
   ObjCInterfaceDecl *CurrentIDecl;
   ObjCInterfaceDecl *CurrentIDecl;
 };
 };
@@ -549,11 +553,10 @@ ActOnSuperClassOfClassInterface(Scope *S,
   if (!PrevDecl) {
   if (!PrevDecl) {
     // Try to correct for a typo in the superclass name without correcting
     // Try to correct for a typo in the superclass name without correcting
     // to the class we're defining.
     // to the class we're defining.
+    ObjCInterfaceValidatorCCC CCC(IDecl);
     if (TypoCorrection Corrected = CorrectTypo(
     if (TypoCorrection Corrected = CorrectTypo(
-            DeclarationNameInfo(SuperName, SuperLoc),
-            LookupOrdinaryName, TUScope,
-            nullptr, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
-            CTK_ErrorRecovery)) {
+            DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName,
+            TUScope, nullptr, CCC, CTK_ErrorRecovery)) {
       diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
       diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
                    << SuperName << ClassName);
                    << SuperName << ClassName);
       PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
       PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
@@ -1292,11 +1295,10 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
   for (const IdentifierLocPair &Pair : ProtocolId) {
   for (const IdentifierLocPair &Pair : ProtocolId) {
     ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second);
     ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second);
     if (!PDecl) {
     if (!PDecl) {
+      DeclFilterCCC<ObjCProtocolDecl> CCC{};
       TypoCorrection Corrected = CorrectTypo(
       TypoCorrection Corrected = CorrectTypo(
-          DeclarationNameInfo(Pair.first, Pair.second),
-          LookupObjCProtocolName, TUScope, nullptr,
-          llvm::make_unique<DeclFilterCCC<ObjCProtocolDecl>>(),
-          CTK_ErrorRecovery);
+          DeclarationNameInfo(Pair.first, Pair.second), LookupObjCProtocolName,
+          TUScope, nullptr, CCC, CTK_ErrorRecovery);
       if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
       if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
         diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest)
         diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest)
                                     << Pair.first);
                                     << Pair.first);
@@ -1334,7 +1336,8 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
 namespace {
 namespace {
 // Callback to only accept typo corrections that are either
 // Callback to only accept typo corrections that are either
 // Objective-C protocols or valid Objective-C type arguments.
 // Objective-C protocols or valid Objective-C type arguments.
-class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback {
+class ObjCTypeArgOrProtocolValidatorCCC final
+    : public CorrectionCandidateCallback {
   ASTContext &Context;
   ASTContext &Context;
   Sema::LookupNameKind LookupKind;
   Sema::LookupNameKind LookupKind;
  public:
  public:
@@ -1381,6 +1384,10 @@ class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback {
 
 
     return false;
     return false;
   }
   }
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(*this);
+  }
 };
 };
 } // end anonymous namespace
 } // end anonymous namespace
 
 
@@ -1670,12 +1677,10 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
     }
     }
 
 
     // Perform typo correction on the name.
     // Perform typo correction on the name.
-    TypoCorrection corrected = CorrectTypo(
-        DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S,
-        nullptr,
-        llvm::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(Context,
-                                                             lookupKind),
-        CTK_ErrorRecovery);
+    ObjCTypeArgOrProtocolValidatorCCC CCC(Context, lookupKind);
+    TypoCorrection corrected =
+        CorrectTypo(DeclarationNameInfo(identifiers[i], identifierLocs[i]),
+                    lookupKind, S, nullptr, CCC, CTK_ErrorRecovery);
     if (corrected) {
     if (corrected) {
       // Did we find a protocol?
       // Did we find a protocol?
       if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) {
       if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) {
@@ -1967,9 +1972,10 @@ Decl *Sema::ActOnStartClassImplementation(
   } else {
   } else {
     // We did not find anything with the name ClassName; try to correct for
     // We did not find anything with the name ClassName; try to correct for
     // typos in the class name.
     // typos in the class name.
-    TypoCorrection Corrected = CorrectTypo(
-        DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
-        nullptr, llvm::make_unique<ObjCInterfaceValidatorCCC>(), CTK_NonError);
+    ObjCInterfaceValidatorCCC CCC{};
+    TypoCorrection Corrected =
+        CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc),
+                    LookupOrdinaryName, TUScope, nullptr, CCC, CTK_NonError);
     if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
     if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
       // Suggest the (potentially) correct interface name. Don't provide a
       // Suggest the (potentially) correct interface name. Don't provide a
       // code-modification hint or use the typo name for recovery, because
       // code-modification hint or use the typo name for recovery, because

+ 28 - 24
lib/Sema/SemaExpr.cpp

@@ -911,8 +911,9 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
     UnqualifiedId Name;
     UnqualifiedId Name;
     Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
     Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
                        E->getBeginLoc());
                        E->getBeginLoc());
-    ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc,
-                                          Name, true, false);
+    ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, Name,
+                                          /*HasTrailingLParen=*/true,
+                                          /*IsAddressOfOperand=*/false);
     if (TrapFn.isInvalid())
     if (TrapFn.isInvalid())
       return ExprError();
       return ExprError();
 
 
@@ -1905,11 +1906,10 @@ static void emitEmptyLookupTypoDiagnostic(
 /// Diagnose an empty lookup.
 /// Diagnose an empty lookup.
 ///
 ///
 /// \return false if new lookup candidates were found
 /// \return false if new lookup candidates were found
-bool
-Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
-                          std::unique_ptr<CorrectionCandidateCallback> CCC,
-                          TemplateArgumentListInfo *ExplicitTemplateArgs,
-                          ArrayRef<Expr *> Args, TypoExpr **Out) {
+bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+                               CorrectionCandidateCallback &CCC,
+                               TemplateArgumentListInfo *ExplicitTemplateArgs,
+                               ArrayRef<Expr *> Args, TypoExpr **Out) {
   DeclarationName Name = R.getLookupName();
   DeclarationName Name = R.getLookupName();
 
 
   unsigned diagnostic = diag::err_undeclared_var_use;
   unsigned diagnostic = diag::err_undeclared_var_use;
@@ -1998,7 +1998,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
     assert(!ExplicitTemplateArgs &&
     assert(!ExplicitTemplateArgs &&
            "Diagnosing an empty lookup with explicit template args!");
            "Diagnosing an empty lookup with explicit template args!");
     *Out = CorrectTypoDelayed(
     *Out = CorrectTypoDelayed(
-        R.getLookupNameInfo(), R.getLookupKind(), S, &SS, std::move(CCC),
+        R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC,
         [=](const TypoCorrection &TC) {
         [=](const TypoCorrection &TC) {
           emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args,
           emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args,
                                         diagnostic, diagnostic_suggest);
                                         diagnostic, diagnostic_suggest);
@@ -2006,9 +2006,9 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
         nullptr, CTK_ErrorRecovery);
         nullptr, CTK_ErrorRecovery);
     if (*Out)
     if (*Out)
       return true;
       return true;
-  } else if (S && (Corrected =
-                       CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S,
-                                   &SS, std::move(CCC), CTK_ErrorRecovery))) {
+  } else if (S &&
+             (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
+                                      S, &SS, CCC, CTK_ErrorRecovery))) {
     std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
     std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
     bool DroppedSpecifier =
     bool DroppedSpecifier =
         Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
         Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
@@ -2157,7 +2157,7 @@ ExprResult
 Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
 Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
                         SourceLocation TemplateKWLoc, UnqualifiedId &Id,
                         SourceLocation TemplateKWLoc, UnqualifiedId &Id,
                         bool HasTrailingLParen, bool IsAddressOfOperand,
                         bool HasTrailingLParen, bool IsAddressOfOperand,
-                        std::unique_ptr<CorrectionCandidateCallback> CCC,
+                        CorrectionCandidateCallback *CCC,
                         bool IsInlineAsmIdentifier, Token *KeywordReplacement) {
                         bool IsInlineAsmIdentifier, Token *KeywordReplacement) {
   assert(!(IsAddressOfOperand && HasTrailingLParen) &&
   assert(!(IsAddressOfOperand && HasTrailingLParen) &&
          "cannot be direct & operand and have a trailing lparen");
          "cannot be direct & operand and have a trailing lparen");
@@ -2279,9 +2279,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
     // If this name wasn't predeclared and if this is not a function
     // If this name wasn't predeclared and if this is not a function
     // call, diagnose the problem.
     // call, diagnose the problem.
     TypoExpr *TE = nullptr;
     TypoExpr *TE = nullptr;
-    auto DefaultValidator = llvm::make_unique<CorrectionCandidateCallback>(
-        II, SS.isValid() ? SS.getScopeRep() : nullptr);
-    DefaultValidator->IsAddressOfOperand = IsAddressOfOperand;
+    DefaultFilterCCC DefaultValidator(II, SS.isValid() ? SS.getScopeRep()
+                                                       : nullptr);
+    DefaultValidator.IsAddressOfOperand = IsAddressOfOperand;
     assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
     assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
            "Typo correction callback misconfigured");
            "Typo correction callback misconfigured");
     if (CCC) {
     if (CCC) {
@@ -2293,9 +2293,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
     // FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for
     // FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for
     // a template name, but we happen to have always already looked up the name
     // a template name, but we happen to have always already looked up the name
     // before we get here if it must be a template name.
     // before we get here if it must be a template name.
-    if (DiagnoseEmptyLookup(S, SS, R,
-                            CCC ? std::move(CCC) : std::move(DefaultValidator),
-                            nullptr, None, &TE)) {
+    if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator, nullptr,
+                            None, &TE)) {
       if (TE && KeywordReplacement) {
       if (TE && KeywordReplacement) {
         auto &State = getTypoExprState(TE);
         auto &State = getTypoExprState(TE);
         auto BestTC = State.Consumer->getNextCorrection();
         auto BestTC = State.Consumer->getNextCorrection();
@@ -2549,8 +2548,10 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
       SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
       SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
       CXXScopeSpec SelfScopeSpec;
       CXXScopeSpec SelfScopeSpec;
       SourceLocation TemplateKWLoc;
       SourceLocation TemplateKWLoc;
-      ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc,
-                                              SelfName, false, false);
+      ExprResult SelfExpr =
+          ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName,
+                            /*HasTrailingLParen=*/false,
+                            /*IsAddressOfOperand=*/false);
       if (SelfExpr.isInvalid())
       if (SelfExpr.isInvalid())
         return ExprError();
         return ExprError();
 
 
@@ -4893,7 +4894,7 @@ Sema::getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto,
 }
 }
 
 
 namespace {
 namespace {
-class FunctionCallCCC : public FunctionCallFilterCCC {
+class FunctionCallCCC final : public FunctionCallFilterCCC {
 public:
 public:
   FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName,
   FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName,
                   unsigned NumArgs, MemberExpr *ME)
                   unsigned NumArgs, MemberExpr *ME)
@@ -4909,6 +4910,10 @@ public:
     return FunctionCallFilterCCC::ValidateCandidate(candidate);
     return FunctionCallFilterCCC::ValidateCandidate(candidate);
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<FunctionCallCCC>(*this);
+  }
+
 private:
 private:
   const IdentifierInfo *const FunctionName;
   const IdentifierInfo *const FunctionName;
 };
 };
@@ -4921,11 +4926,10 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
   DeclarationName FuncName = FDecl->getDeclName();
   DeclarationName FuncName = FDecl->getDeclName();
   SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getBeginLoc();
   SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getBeginLoc();
 
 
+  FunctionCallCCC CCC(S, FuncName.getAsIdentifierInfo(), Args.size(), ME);
   if (TypoCorrection Corrected = S.CorrectTypo(
   if (TypoCorrection Corrected = S.CorrectTypo(
           DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName,
           DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName,
-          S.getScopeForContext(S.CurContext), nullptr,
-          llvm::make_unique<FunctionCallCCC>(S, FuncName.getAsIdentifierInfo(),
-                                             Args.size(), ME),
+          S.getScopeForContext(S.CurContext), nullptr, CCC,
           Sema::CTK_ErrorRecovery)) {
           Sema::CTK_ErrorRecovery)) {
     if (NamedDecl *ND = Corrected.getFoundDecl()) {
     if (NamedDecl *ND = Corrected.getFoundDecl()) {
       if (Corrected.isOverloaded()) {
       if (Corrected.isOverloaded()) {

+ 10 - 6
lib/Sema/SemaExprMember.cpp

@@ -590,7 +590,7 @@ namespace {
 // Callback to only accept typo corrections that are either a ValueDecl or a
 // Callback to only accept typo corrections that are either a ValueDecl or a
 // FunctionTemplateDecl and are declared in the current record or, for a C++
 // FunctionTemplateDecl and are declared in the current record or, for a C++
 // classes, one of its base classes.
 // classes, one of its base classes.
-class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
+class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
 public:
 public:
   explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
   explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
       : Record(RTy->getDecl()) {
       : Record(RTy->getDecl()) {
@@ -628,6 +628,10 @@ public:
     return false;
     return false;
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<RecordMemberExprValidatorCCC>(*this);
+  }
+
 private:
 private:
   const RecordDecl *const Record;
   const RecordDecl *const Record;
 };
 };
@@ -696,9 +700,9 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
   };
   };
   QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
   QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
                   R.redeclarationKind()};
                   R.redeclarationKind()};
+  RecordMemberExprValidatorCCC CCC(RTy);
   TE = SemaRef.CorrectTypoDelayed(
   TE = SemaRef.CorrectTypoDelayed(
-      R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS,
-      llvm::make_unique<RecordMemberExprValidatorCCC>(RTy),
+      R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC,
       [=, &SemaRef](const TypoCorrection &TC) {
       [=, &SemaRef](const TypoCorrection &TC) {
         if (TC) {
         if (TC) {
           assert(!TC.isKeyword() &&
           assert(!TC.isKeyword() &&
@@ -1331,11 +1335,11 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
 
 
     if (!IV) {
     if (!IV) {
       // Attempt to correct for typos in ivar names.
       // Attempt to correct for typos in ivar names.
-      auto Validator = llvm::make_unique<DeclFilterCCC<ObjCIvarDecl>>();
-      Validator->IsObjCIvarLookup = IsArrow;
+      DeclFilterCCC<ObjCIvarDecl> Validator{};
+      Validator.IsObjCIvarLookup = IsArrow;
       if (TypoCorrection Corrected = S.CorrectTypo(
       if (TypoCorrection Corrected = S.CorrectTypo(
               R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
               R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
-              std::move(Validator), Sema::CTK_ErrorRecovery, IDecl)) {
+              Validator, Sema::CTK_ErrorRecovery, IDecl)) {
         IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
         IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
         S.diagnoseTypo(
         S.diagnoseTypo(
             Corrected,
             Corrected,

+ 11 - 8
lib/Sema/SemaExprObjC.cpp

@@ -1946,11 +1946,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
   }
   }
 
 
   // Attempt to correct for typos in property names.
   // Attempt to correct for typos in property names.
-  if (TypoCorrection Corrected =
-          CorrectTypo(DeclarationNameInfo(MemberName, MemberLoc),
-                      LookupOrdinaryName, nullptr, nullptr,
-                      llvm::make_unique<DeclFilterCCC<ObjCPropertyDecl>>(),
-                      CTK_ErrorRecovery, IFace, false, OPT)) {
+  DeclFilterCCC<ObjCPropertyDecl> CCC{};
+  if (TypoCorrection Corrected = CorrectTypo(
+          DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName,
+          nullptr, nullptr, CCC, CTK_ErrorRecovery, IFace, false, OPT)) {
     DeclarationName TypoResult = Corrected.getCorrection();
     DeclarationName TypoResult = Corrected.getCorrection();
     if (TypoResult.isIdentifier() &&
     if (TypoResult.isIdentifier() &&
         TypoResult.getAsIdentifierInfo() == Member) {
         TypoResult.getAsIdentifierInfo() == Member) {
@@ -2107,7 +2106,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
 
 
 namespace {
 namespace {
 
 
-class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback {
+class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback {
  public:
  public:
   ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {
   ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {
     // Determine whether "super" is acceptable in the current context.
     // Determine whether "super" is acceptable in the current context.
@@ -2119,6 +2118,10 @@ class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback {
     return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
     return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
         candidate.isKeyword("super");
         candidate.isKeyword("super");
   }
   }
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<ObjCInterfaceOrSuperCCC>(*this);
+  }
 };
 };
 
 
 } // end anonymous namespace
 } // end anonymous namespace
@@ -2194,9 +2197,9 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
   }
   }
   }
   }
 
 
+  ObjCInterfaceOrSuperCCC CCC(getCurMethodDecl());
   if (TypoCorrection Corrected = CorrectTypo(
   if (TypoCorrection Corrected = CorrectTypo(
-          Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr,
-          llvm::make_unique<ObjCInterfaceOrSuperCCC>(getCurMethodDecl()),
+          Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, CCC,
           CTK_ErrorRecovery, nullptr, false, nullptr, false)) {
           CTK_ErrorRecovery, nullptr, false, nullptr, false)) {
     if (Corrected.isKeyword()) {
     if (Corrected.isKeyword()) {
       // If we've found the keyword "super" (the only keyword that would be
       // If we've found the keyword "super" (the only keyword that would be

+ 7 - 3
lib/Sema/SemaInit.cpp

@@ -2208,7 +2208,7 @@ namespace {
 
 
 // Callback to only accept typo corrections that are for field members of
 // Callback to only accept typo corrections that are for field members of
 // the given struct or union.
 // the given struct or union.
-class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
+class FieldInitializerValidatorCCC final : public CorrectionCandidateCallback {
  public:
  public:
   explicit FieldInitializerValidatorCCC(RecordDecl *RD)
   explicit FieldInitializerValidatorCCC(RecordDecl *RD)
       : Record(RD) {}
       : Record(RD) {}
@@ -2218,6 +2218,10 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
     return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record);
     return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record);
   }
   }
 
 
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<FieldInitializerValidatorCCC>(*this);
+  }
+
  private:
  private:
   RecordDecl *Record;
   RecordDecl *Record;
 };
 };
@@ -2420,10 +2424,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
 
 
         // Name lookup didn't find anything.
         // Name lookup didn't find anything.
         // Determine whether this was a typo for another field name.
         // Determine whether this was a typo for another field name.
+        FieldInitializerValidatorCCC CCC(RT->getDecl());
         if (TypoCorrection Corrected = SemaRef.CorrectTypo(
         if (TypoCorrection Corrected = SemaRef.CorrectTypo(
                 DeclarationNameInfo(FieldName, D->getFieldLoc()),
                 DeclarationNameInfo(FieldName, D->getFieldLoc()),
-                Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr,
-                llvm::make_unique<FieldInitializerValidatorCCC>(RT->getDecl()),
+                Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr, CCC,
                 Sema::CTK_ErrorRecovery, RT->getDecl())) {
                 Sema::CTK_ErrorRecovery, RT->getDecl())) {
           SemaRef.diagnoseTypo(
           SemaRef.diagnoseTypo(
               Corrected,
               Corrected,

+ 2 - 2
lib/Sema/SemaLambda.cpp

@@ -1079,8 +1079,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
       if (R.empty()) {
       if (R.empty()) {
         // FIXME: Disable corrections that would add qualification?
         // FIXME: Disable corrections that would add qualification?
         CXXScopeSpec ScopeSpec;
         CXXScopeSpec ScopeSpec;
-        if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R,
-                                llvm::make_unique<DeclFilterCCC<VarDecl>>()))
+        DeclFilterCCC<VarDecl> Validator{};
+        if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
           continue;
           continue;
       }
       }
 
 

+ 22 - 21
lib/Sema/SemaLookup.cpp

@@ -4572,8 +4572,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
 
 
 std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
 std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
     const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
     const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
-    Scope *S, CXXScopeSpec *SS,
-    std::unique_ptr<CorrectionCandidateCallback> CCC,
+    Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
     DeclContext *MemberContext, bool EnteringContext,
     DeclContext *MemberContext, bool EnteringContext,
     const ObjCObjectPointerType *OPT, bool ErrorRecovery) {
     const ObjCObjectPointerType *OPT, bool ErrorRecovery) {
 
 
@@ -4635,9 +4634,13 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
                                            TypoName.getBeginLoc());
                                            TypoName.getBeginLoc());
   }
   }
 
 
-  CorrectionCandidateCallback &CCCRef = *CCC;
+  // Extend the lifetime of the callback. We delayed this until here
+  // to avoid allocations in the hot path (which is where no typo correction
+  // occurs). Note that CorrectionCandidateCallback is polymorphic and
+  // initially stack-allocated.
+  std::unique_ptr<CorrectionCandidateCallback> ClonedCCC = CCC.clone();
   auto Consumer = llvm::make_unique<TypoCorrectionConsumer>(
   auto Consumer = llvm::make_unique<TypoCorrectionConsumer>(
-      *this, TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
+      *this, TypoName, LookupKind, S, SS, std::move(ClonedCCC), MemberContext,
       EnteringContext);
       EnteringContext);
 
 
   // Perform name lookup to find visible, similarly-named entities.
   // Perform name lookup to find visible, similarly-named entities.
@@ -4689,7 +4692,9 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
     }
     }
   }
   }
 
 
-  AddKeywordsToConsumer(*this, *Consumer, S, CCCRef, SS && SS->isNotEmpty());
+  AddKeywordsToConsumer(*this, *Consumer, S,
+                        *Consumer->getCorrectionValidator(),
+                        SS && SS->isNotEmpty());
 
 
   // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going
   // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going
   // to search those namespaces.
   // to search those namespaces.
@@ -4743,19 +4748,18 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
 TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
 TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
                                  Sema::LookupNameKind LookupKind,
                                  Sema::LookupNameKind LookupKind,
                                  Scope *S, CXXScopeSpec *SS,
                                  Scope *S, CXXScopeSpec *SS,
-                                 std::unique_ptr<CorrectionCandidateCallback> CCC,
+                                 CorrectionCandidateCallback &CCC,
                                  CorrectTypoKind Mode,
                                  CorrectTypoKind Mode,
                                  DeclContext *MemberContext,
                                  DeclContext *MemberContext,
                                  bool EnteringContext,
                                  bool EnteringContext,
                                  const ObjCObjectPointerType *OPT,
                                  const ObjCObjectPointerType *OPT,
                                  bool RecordFailure) {
                                  bool RecordFailure) {
-  assert(CCC && "CorrectTypo requires a CorrectionCandidateCallback");
-
   // Always let the ExternalSource have the first chance at correction, even
   // Always let the ExternalSource have the first chance at correction, even
   // if we would otherwise have given up.
   // if we would otherwise have given up.
   if (ExternalSource) {
   if (ExternalSource) {
-    if (TypoCorrection Correction = ExternalSource->CorrectTypo(
-        TypoName, LookupKind, S, SS, *CCC, MemberContext, EnteringContext, OPT))
+    if (TypoCorrection Correction =
+            ExternalSource->CorrectTypo(TypoName, LookupKind, S, SS, CCC,
+                                        MemberContext, EnteringContext, OPT))
       return Correction;
       return Correction;
   }
   }
 
 
@@ -4763,12 +4767,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
   // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
   // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
   // some instances of CTC_Unknown, while WantRemainingKeywords is true
   // some instances of CTC_Unknown, while WantRemainingKeywords is true
   // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
   // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
-  bool ObjCMessageReceiver = CCC->WantObjCSuper && !CCC->WantRemainingKeywords;
+  bool ObjCMessageReceiver = CCC.WantObjCSuper && !CCC.WantRemainingKeywords;
 
 
   IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
   IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
-  auto Consumer = makeTypoCorrectionConsumer(
-      TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
-      EnteringContext, OPT, Mode == CTK_ErrorRecovery);
+  auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC,
+                                             MemberContext, EnteringContext,
+                                             OPT, Mode == CTK_ErrorRecovery);
 
 
   if (!Consumer)
   if (!Consumer)
     return TypoCorrection();
     return TypoCorrection();
@@ -4878,16 +4882,13 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
 /// needed.
 /// needed.
 TypoExpr *Sema::CorrectTypoDelayed(
 TypoExpr *Sema::CorrectTypoDelayed(
     const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
     const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
-    Scope *S, CXXScopeSpec *SS,
-    std::unique_ptr<CorrectionCandidateCallback> CCC,
+    Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
     TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode,
     TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode,
     DeclContext *MemberContext, bool EnteringContext,
     DeclContext *MemberContext, bool EnteringContext,
     const ObjCObjectPointerType *OPT) {
     const ObjCObjectPointerType *OPT) {
-  assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback");
-
-  auto Consumer = makeTypoCorrectionConsumer(
-      TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
-      EnteringContext, OPT, Mode == CTK_ErrorRecovery);
+  auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC,
+                                             MemberContext, EnteringContext,
+                                             OPT, Mode == CTK_ErrorRecovery);
 
 
   // Give the external sema source a chance to correct the typo.
   // Give the external sema source a chance to correct the typo.
   TypoCorrection ExternalTypo;
   TypoCorrection ExternalTypo;

+ 15 - 5
lib/Sema/SemaOpenMP.cpp

@@ -1955,6 +1955,11 @@ public:
     }
     }
     return false;
     return false;
   }
   }
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<VarDeclFilterCCC>(*this);
+  }
+
 };
 };
 
 
 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
@@ -1972,6 +1977,10 @@ public:
     }
     }
     return false;
     return false;
   }
   }
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<VarOrFuncDeclFilterCCC>(*this);
+  }
 };
 };
 
 
 } // namespace
 } // namespace
@@ -1988,9 +1997,10 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
 
 
   VarDecl *VD;
   VarDecl *VD;
   if (!Lookup.isSingleResult()) {
   if (!Lookup.isSingleResult()) {
-    if (TypoCorrection Corrected = CorrectTypo(
-            Id, LookupOrdinaryName, CurScope, nullptr,
-            llvm::make_unique<VarDeclFilterCCC>(*this), CTK_ErrorRecovery)) {
+    VarDeclFilterCCC CCC(*this);
+    if (TypoCorrection Corrected =
+            CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
+                        CTK_ErrorRecovery)) {
       diagnoseTypo(Corrected,
       diagnoseTypo(Corrected,
                    PDiag(Lookup.empty()
                    PDiag(Lookup.empty()
                              ? diag::err_undeclared_var_use_suggest
                              ? diag::err_undeclared_var_use_suggest
@@ -14379,9 +14389,9 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
   Lookup.suppressDiagnostics();
   Lookup.suppressDiagnostics();
 
 
   if (!Lookup.isSingleResult()) {
   if (!Lookup.isSingleResult()) {
+    VarOrFuncDeclFilterCCC CCC(*this);
     if (TypoCorrection Corrected =
     if (TypoCorrection Corrected =
-            CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr,
-                        llvm::make_unique<VarOrFuncDeclFilterCCC>(*this),
+            CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
                         CTK_ErrorRecovery)) {
                         CTK_ErrorRecovery)) {
       diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
       diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
                                   << Id.getName());
                                   << Id.getName());

+ 16 - 19
lib/Sema/SemaOverload.cpp

@@ -11892,15 +11892,6 @@ public:
 
 
 }
 }
 
 
-static std::unique_ptr<CorrectionCandidateCallback>
-MakeValidator(Sema &SemaRef, MemberExpr *ME, size_t NumArgs,
-              bool HasTemplateArgs, bool AllowTypoCorrection) {
-  if (!AllowTypoCorrection)
-    return llvm::make_unique<NoTypoCorrectionCCC>();
-  return llvm::make_unique<FunctionCallFilterCCC>(SemaRef, NumArgs,
-                                                  HasTemplateArgs, ME);
-}
-
 /// Attempts to recover from a call where no functions were found.
 /// Attempts to recover from a call where no functions were found.
 ///
 ///
 /// Returns true if new candidates were found.
 /// Returns true if new candidates were found.
@@ -11935,16 +11926,22 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
   LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
   LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
                  Sema::LookupOrdinaryName);
                  Sema::LookupOrdinaryName);
   bool DoDiagnoseEmptyLookup = EmptyLookup;
   bool DoDiagnoseEmptyLookup = EmptyLookup;
-  if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
-                              OverloadCandidateSet::CSK_Normal,
-                              ExplicitTemplateArgs, Args,
-                              &DoDiagnoseEmptyLookup) &&
-    (!DoDiagnoseEmptyLookup || SemaRef.DiagnoseEmptyLookup(
-        S, SS, R,
-        MakeValidator(SemaRef, dyn_cast<MemberExpr>(Fn), Args.size(),
-                      ExplicitTemplateArgs != nullptr, AllowTypoCorrection),
-        ExplicitTemplateArgs, Args)))
-    return ExprError();
+  if (!DiagnoseTwoPhaseLookup(
+          SemaRef, Fn->getExprLoc(), SS, R, OverloadCandidateSet::CSK_Normal,
+          ExplicitTemplateArgs, Args, &DoDiagnoseEmptyLookup)) {
+    NoTypoCorrectionCCC NoTypoValidator{};
+    FunctionCallFilterCCC FunctionCallValidator(SemaRef, Args.size(),
+                                                ExplicitTemplateArgs != nullptr,
+                                                dyn_cast<MemberExpr>(Fn));
+    CorrectionCandidateCallback &Validator =
+        AllowTypoCorrection
+            ? static_cast<CorrectionCandidateCallback &>(FunctionCallValidator)
+            : static_cast<CorrectionCandidateCallback &>(NoTypoValidator);
+    if (!DoDiagnoseEmptyLookup ||
+        SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator, ExplicitTemplateArgs,
+                                    Args))
+      return ExprError();
+  }
 
 
   assert(!R.empty() && "lookup results empty despite recovery");
   assert(!R.empty() && "lookup results empty despite recovery");
 
 

+ 15 - 12
lib/Sema/SemaTemplate.cpp

@@ -410,14 +410,14 @@ bool Sema::LookupTemplateName(LookupResult &Found,
     DeclarationName Name = Found.getLookupName();
     DeclarationName Name = Found.getLookupName();
     Found.clear();
     Found.clear();
     // Simple filter callback that, for keywords, only accepts the C++ *_cast
     // Simple filter callback that, for keywords, only accepts the C++ *_cast
-    auto FilterCCC = llvm::make_unique<CorrectionCandidateCallback>();
-    FilterCCC->WantTypeSpecifiers = false;
-    FilterCCC->WantExpressionKeywords = false;
-    FilterCCC->WantRemainingKeywords = false;
-    FilterCCC->WantCXXNamedCasts = true;
-    if (TypoCorrection Corrected = CorrectTypo(
-            Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS,
-            std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) {
+    DefaultFilterCCC FilterCCC{};
+    FilterCCC.WantTypeSpecifiers = false;
+    FilterCCC.WantExpressionKeywords = false;
+    FilterCCC.WantRemainingKeywords = false;
+    FilterCCC.WantCXXNamedCasts = true;
+    if (TypoCorrection Corrected =
+            CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S,
+                        &SS, FilterCCC, CTK_ErrorRecovery, LookupCtx)) {
       Found.setLookupName(Corrected.getCorrection());
       Found.setLookupName(Corrected.getCorrection());
       if (auto *ND = Corrected.getFoundDecl())
       if (auto *ND = Corrected.getFoundDecl())
         Found.addDecl(ND);
         Found.addDecl(ND);
@@ -579,13 +579,16 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
         return S.getAsTemplateNameDecl(ND);
         return S.getAsTemplateNameDecl(ND);
       return Candidate.isKeyword();
       return Candidate.isKeyword();
     }
     }
+
+    std::unique_ptr<CorrectionCandidateCallback> clone() override {
+      return llvm::make_unique<TemplateCandidateFilter>(*this);
+    }
   };
   };
 
 
   DeclarationName Name = NameInfo.getName();
   DeclarationName Name = NameInfo.getName();
-  if (TypoCorrection Corrected =
-          CorrectTypo(NameInfo, LookupKind, S, &SS,
-                      llvm::make_unique<TemplateCandidateFilter>(*this),
-                      CTK_ErrorRecovery, LookupCtx)) {
+  TemplateCandidateFilter CCC(*this);
+  if (TypoCorrection Corrected = CorrectTypo(NameInfo, LookupKind, S, &SS, CCC,
+                                             CTK_ErrorRecovery, LookupCtx)) {
     auto *ND = Corrected.getFoundDecl();
     auto *ND = Corrected.getFoundDecl();
     if (ND)
     if (ND)
       ND = getAsTemplateNameDecl(ND);
       ND = getAsTemplateNameDecl(ND);

+ 9 - 5
lib/Sema/SemaTemplateVariadic.cpp

@@ -924,12 +924,16 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
 namespace {
 namespace {
 
 
 // Callback to only accept typo corrections that refer to parameter packs.
 // Callback to only accept typo corrections that refer to parameter packs.
-class ParameterPackValidatorCCC : public CorrectionCandidateCallback {
+class ParameterPackValidatorCCC final : public CorrectionCandidateCallback {
  public:
  public:
   bool ValidateCandidate(const TypoCorrection &candidate) override {
   bool ValidateCandidate(const TypoCorrection &candidate) override {
     NamedDecl *ND = candidate.getCorrectionDecl();
     NamedDecl *ND = candidate.getCorrectionDecl();
     return ND && ND->isParameterPack();
     return ND && ND->isParameterPack();
   }
   }
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return llvm::make_unique<ParameterPackValidatorCCC>(*this);
+  }
 };
 };
 
 
 }
 }
@@ -965,18 +969,18 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
     break;
     break;
 
 
   case LookupResult::NotFound:
   case LookupResult::NotFound:
-  case LookupResult::NotFoundInCurrentInstantiation:
+  case LookupResult::NotFoundInCurrentInstantiation: {
+    ParameterPackValidatorCCC CCC{};
     if (TypoCorrection Corrected =
     if (TypoCorrection Corrected =
             CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr,
             CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr,
-                        llvm::make_unique<ParameterPackValidatorCCC>(),
-                        CTK_ErrorRecovery)) {
+                        CCC, CTK_ErrorRecovery)) {
       diagnoseTypo(Corrected,
       diagnoseTypo(Corrected,
                    PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name,
                    PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name,
                    PDiag(diag::note_parameter_pack_here));
                    PDiag(diag::note_parameter_pack_here));
       ParameterPack = Corrected.getCorrectionDecl();
       ParameterPack = Corrected.getCorrectionDecl();
     }
     }
     break;
     break;
-
+  }
   case LookupResult::FoundOverloaded:
   case LookupResult::FoundOverloaded:
   case LookupResult::FoundUnresolvedValue:
   case LookupResult::FoundUnresolvedValue:
     break;
     break;

+ 6 - 3
lib/Sema/SemaType.cpp

@@ -5913,7 +5913,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
       id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
       id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
 
 
       ExprResult AddrSpace = S.ActOnIdExpression(
       ExprResult AddrSpace = S.ActOnIdExpression(
-          S.getCurScope(), SS, TemplateKWLoc, id, false, false);
+          S.getCurScope(), SS, TemplateKWLoc, id, /*HasTrailingLParen=*/false,
+          /*IsAddressOfOperand=*/false);
       if (AddrSpace.isInvalid())
       if (AddrSpace.isInvalid())
         return;
         return;
 
 
@@ -7043,7 +7044,8 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
     Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
     Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
 
 
     ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
     ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
-                                          Id, false, false);
+                                          Id, /*HasTrailingLParen=*/false,
+                                          /*IsAddressOfOperand=*/false);
 
 
     if (Size.isInvalid())
     if (Size.isInvalid())
       return;
       return;
@@ -7080,7 +7082,8 @@ static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
     id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
     id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
 
 
     ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
     ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
-                                          id, false, false);
+                                          id, /*HasTrailingLParen=*/false,
+                                          /*IsAddressOfOperand=*/false);
     if (Size.isInvalid())
     if (Size.isInvalid())
       return;
       return;