Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
Line
Count
Source (jump to first uncovered line)
1
//===- TypoCorrection.h - Class for typo correction results -----*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file defines the TypoCorrection class, which stores the results of
10
// Sema's typo correction (Sema::CorrectTypo).
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H
15
#define LLVM_CLANG_SEMA_TYPOCORRECTION_H
16
17
#include "clang/AST/Decl.h"
18
#include "clang/AST/DeclarationName.h"
19
#include "clang/Basic/LLVM.h"
20
#include "clang/Basic/PartialDiagnostic.h"
21
#include "clang/Basic/SourceLocation.h"
22
#include "clang/Sema/DeclSpec.h"
23
#include "llvm/ADT/ArrayRef.h"
24
#include "llvm/ADT/SmallVector.h"
25
#include "llvm/Support/Casting.h"
26
#include <cstddef>
27
#include <limits>
28
#include <string>
29
#include <utility>
30
#include <vector>
31
32
namespace clang {
33
34
class DeclContext;
35
class IdentifierInfo;
36
class LangOptions;
37
class MemberExpr;
38
class NestedNameSpecifier;
39
class Sema;
40
41
/// Simple class containing the result of Sema::CorrectTypo
42
class TypoCorrection {
43
public:
44
  // "Distance" for unusable corrections
45
  static const unsigned InvalidDistance = std::numeric_limits<unsigned>::max();
46
47
  // The largest distance still considered valid (larger edit distances are
48
  // mapped to InvalidDistance by getEditDistance).
49
  static const unsigned MaximumDistance = 10000U;
50
51
  // Relative weightings of the "edit distance" components. The higher the
52
  // weight, the more of a penalty to fitness the component will give (higher
53
  // weights mean greater contribution to the total edit distance, with the
54
  // best correction candidates having the lowest edit distance).
55
  static const unsigned CharDistanceWeight = 100U;
56
  static const unsigned QualifierDistanceWeight = 110U;
57
  static const unsigned CallbackDistanceWeight = 150U;
58
59
  TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
60
                 NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0,
61
                 unsigned QualifierDistance = 0)
62
      : CorrectionName(Name), CorrectionNameSpec(NNS),
63
29.7k
        CharDistance(CharDistance), QualifierDistance(QualifierDistance) {
64
29.7k
    if (NameDecl)
65
0
      CorrectionDecls.push_back(NameDecl);
66
29.7k
  }
67
68
  TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr,
69
                 unsigned CharDistance = 0)
70
      : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
71
0
        CharDistance(CharDistance) {
72
0
    if (Name)
73
0
      CorrectionDecls.push_back(Name);
74
0
  }
75
76
  TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr,
77
                 unsigned CharDistance = 0)
78
      : CorrectionName(Name), CorrectionNameSpec(NNS),
79
        CharDistance(CharDistance) {}
80
81
29.0k
  TypoCorrection() = default;
82
83
  /// Gets the DeclarationName of the typo correction
84
393
  DeclarationName getCorrection() const { return CorrectionName; }
85
86
238k
  IdentifierInfo *getCorrectionAsIdentifierInfo() const {
87
238k
    return CorrectionName.getAsIdentifierInfo();
88
238k
  }
89
90
  /// Gets the NestedNameSpecifier needed to use the typo correction
91
1.34k
  NestedNameSpecifier *getCorrectionSpecifier() const {
92
1.34k
    return CorrectionNameSpec;
93
1.34k
  }
94
95
87.1k
  void setCorrectionSpecifier(NestedNameSpecifier *NNS) {
96
87.1k
    CorrectionNameSpec = NNS;
97
87.1k
    ForceSpecifierReplacement = (NNS != nullptr);
98
87.1k
  }
99
100
3.35k
  void WillReplaceSpecifier(bool ForceReplacement) {
101
3.35k
    ForceSpecifierReplacement = ForceReplacement;
102
3.35k
  }
103
104
6.88k
  bool WillReplaceSpecifier() const {
105
6.88k
    return ForceSpecifierReplacement;
106
6.88k
  }
107
108
87.1k
  void setQualifierDistance(unsigned ED) {
109
87.1k
    QualifierDistance = ED;
110
87.1k
  }
111
112
90.4k
  void setCallbackDistance(unsigned ED) {
113
90.4k
    CallbackDistance = ED;
114
90.4k
  }
115
116
  // Convert the given weighted edit distance to a roughly equivalent number of
117
  // single-character edits (typically for comparison to the length of the
118
  // string being edited).
119
94.5k
  static unsigned NormalizeEditDistance(unsigned ED) {
120
94.5k
    if (ED > MaximumDistance)
121
0
      return InvalidDistance;
122
94.5k
    return (ED + CharDistanceWeight / 2) / CharDistanceWeight;
123
94.5k
  }
124
125
  /// Gets the "edit distance" of the typo correction from the typo.
126
  /// If Normalized is true, scale the distance down by the CharDistanceWeight
127
  /// to return the edit distance in terms of single-character edits.
128
106k
  unsigned getEditDistance(bool Normalized = true) const {
129
106k
    if (CharDistance > MaximumDistance || QualifierDistance > MaximumDistance ||
130
106k
        CallbackDistance > MaximumDistance)
131
1.40k
      return InvalidDistance;
132
104k
    unsigned ED =
133
104k
        CharDistance * CharDistanceWeight +
134
104k
        QualifierDistance * QualifierDistanceWeight +
135
104k
        CallbackDistance * CallbackDistanceWeight;
136
104k
    if (ED > MaximumDistance)
137
0
      return InvalidDistance;
138
104k
    // Half the CharDistanceWeight is added to ED to simulate rounding since
139
104k
    // integer division truncates the value (i.e. round-to-nearest-int instead
140
104k
    // of round-to-zero).
141
104k
    return Normalized ? 
NormalizeEditDistance(ED)90.7k
:
ED14.0k
;
142
104k
  }
143
144
  /// Get the correction declaration found by name lookup (before we
145
  /// looked through using shadow declarations and the like).
146
16.7k
  NamedDecl *getFoundDecl() const {
147
16.7k
    return hasCorrectionDecl() ? 
*(CorrectionDecls.begin())5.96k
:
nullptr10.8k
;
148
16.7k
  }
149
150
  /// Gets the pointer to the declaration of the typo correction
151
15.0k
  NamedDecl *getCorrectionDecl() const {
152
15.0k
    auto *D = getFoundDecl();
153
15.0k
    return D ? 
D->getUnderlyingDecl()4.25k
:
nullptr10.7k
;
154
15.0k
  }
155
  template <class DeclClass>
156
883
  DeclClass *getCorrectionDeclAs() const {
157
883
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
883
  }
clang::FieldDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::FieldDecl>() const
Line
Count
Source
156
197
  DeclClass *getCorrectionDeclAs() const {
157
197
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
197
  }
clang::VarDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::VarDecl>() const
Line
Count
Source
156
53
  DeclClass *getCorrectionDeclAs() const {
157
53
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
53
  }
clang::NamespaceDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::NamespaceDecl>() const
Line
Count
Source
156
15
  DeclClass *getCorrectionDeclAs() const {
157
15
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
15
  }
clang::FunctionDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::FunctionDecl>() const
Line
Count
Source
156
79
  DeclClass *getCorrectionDeclAs() const {
157
79
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
79
  }
clang::ObjCInterfaceDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ObjCInterfaceDecl>() const
Line
Count
Source
156
112
  DeclClass *getCorrectionDeclAs() const {
157
112
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
112
  }
clang::TypeDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::TypeDecl>() const
Line
Count
Source
156
7
  DeclClass *getCorrectionDeclAs() const {
157
7
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
7
  }
clang::ObjCProtocolDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ObjCProtocolDecl>() const
Line
Count
Source
156
10
  DeclClass *getCorrectionDeclAs() const {
157
10
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
10
  }
clang::ImplicitParamDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ImplicitParamDecl>() const
Line
Count
Source
156
334
  DeclClass *getCorrectionDeclAs() const {
157
334
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
334
  }
clang::ObjCIvarDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ObjCIvarDecl>() const
Line
Count
Source
156
22
  DeclClass *getCorrectionDeclAs() const {
157
22
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
22
  }
clang::ObjCPropertyDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::ObjCPropertyDecl>() const
Line
Count
Source
156
19
  DeclClass *getCorrectionDeclAs() const {
157
19
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
19
  }
clang::TemplateDecl* clang::TypoCorrection::getCorrectionDeclAs<clang::TemplateDecl>() const
Line
Count
Source
156
35
  DeclClass *getCorrectionDeclAs() const {
157
35
    return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
158
35
  }
159
160
  /// Clears the list of NamedDecls.
161
87.1k
  void ClearCorrectionDecls() {
162
87.1k
    CorrectionDecls.clear();
163
87.1k
  }
164
165
  /// Clears the list of NamedDecls before adding the new one.
166
312
  void setCorrectionDecl(NamedDecl *CDecl) {
167
312
    CorrectionDecls.clear();
168
312
    addCorrectionDecl(CDecl);
169
312
  }
170
171
  /// Clears the list of NamedDecls and adds the given set.
172
396
  void setCorrectionDecls(ArrayRef<NamedDecl*> Decls) {
173
396
    CorrectionDecls.clear();
174
396
    CorrectionDecls.insert(CorrectionDecls.begin(), Decls.begin(), Decls.end());
175
396
  }
176
177
  /// Add the given NamedDecl to the list of NamedDecls that are the
178
  /// declarations associated with the DeclarationName of this TypoCorrection
179
  void addCorrectionDecl(NamedDecl *CDecl);
180
181
  std::string getAsString(const LangOptions &LO) const;
182
183
996
  std::string getQuoted(const LangOptions &LO) const {
184
996
    return "'" + getAsString(LO) + "'";
185
996
  }
186
187
  /// Returns whether this TypoCorrection has a non-empty DeclarationName
188
29.0k
  explicit operator bool() const { return bool(CorrectionName); }
189
190
  /// Mark this TypoCorrection as being a keyword.
191
  /// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
192
  /// added to the list of the correction's NamedDecl pointers, NULL is added
193
  /// as the only element in the list to mark this TypoCorrection as a keyword.
194
103
  void makeKeyword() {
195
103
    CorrectionDecls.clear();
196
103
    CorrectionDecls.push_back(nullptr);
197
103
    ForceSpecifierReplacement = true;
198
103
  }
199
200
  // Check if this TypoCorrection is a keyword by checking if the first
201
  // item in CorrectionDecls is NULL.
202
30.4k
  bool isKeyword() const {
203
30.4k
    return !CorrectionDecls.empty() && 
CorrectionDecls.front() == nullptr15.0k
;
204
30.4k
  }
205
206
  // Check if this TypoCorrection is the given keyword.
207
  template<std::size_t StrLen>
208
8
  bool isKeyword(const char (&Str)[StrLen]) const {
209
8
    return isKeyword() && 
getCorrectionAsIdentifierInfo()->isStr(Str)5
;
210
8
  }
211
212
  // Returns true if the correction either is a keyword or has a known decl.
213
25.2k
  bool isResolved() const { return !CorrectionDecls.empty(); }
214
215
103
  bool isOverloaded() const {
216
103
    return CorrectionDecls.size() > 1;
217
103
  }
218
219
  void setCorrectionRange(CXXScopeSpec *SS,
220
33.2k
                          const DeclarationNameInfo &TypoName) {
221
33.2k
    CorrectionRange = TypoName.getSourceRange();
222
33.2k
    if (ForceSpecifierReplacement && 
SS1.94k
&&
!SS->isEmpty()1.40k
)
223
541
      CorrectionRange.setBegin(SS->getBeginLoc());
224
33.2k
  }
225
226
3.95k
  SourceRange getCorrectionRange() const {
227
3.95k
    return CorrectionRange;
228
3.95k
  }
229
230
  using decl_iterator = SmallVectorImpl<NamedDecl *>::iterator;
231
232
4.64k
  decl_iterator begin() {
233
4.64k
    return isKeyword() ? 
CorrectionDecls.end()139
:
CorrectionDecls.begin()4.50k
;
234
4.64k
  }
235
236
4.21k
  decl_iterator end() { return CorrectionDecls.end(); }
237
238
  using const_decl_iterator = SmallVectorImpl<NamedDecl *>::const_iterator;
239
240
1.53k
  const_decl_iterator begin() const {
241
1.53k
    return isKeyword() ? 
CorrectionDecls.end()0
: CorrectionDecls.begin();
242
1.53k
  }
243
244
1.53k
  const_decl_iterator end() const { return CorrectionDecls.end(); }
245
246
  /// Returns whether this typo correction is correcting to a
247
  /// declaration that was declared in a module that has not been imported.
248
10.2k
  bool requiresImport() const { return RequiresImport; }
249
4.01k
  void setRequiresImport(bool Req) { RequiresImport = Req; }
250
251
  /// Extra diagnostics are printed after the first diagnostic for the typo.
252
  /// This can be used to attach external notes to the diag.
253
  void addExtraDiagnostic(PartialDiagnostic PD) {
254
    ExtraDiagnostics.push_back(std::move(PD));
255
  }
256
773
  ArrayRef<PartialDiagnostic> getExtraDiagnostics() const {
257
773
    return ExtraDiagnostics;
258
773
  }
259
260
private:
261
16.7k
  bool hasCorrectionDecl() const {
262
16.7k
    return (!isKeyword() && 
!CorrectionDecls.empty()16.5k
);
263
16.7k
  }
264
265
  // Results.
266
  DeclarationName CorrectionName;
267
  NestedNameSpecifier *CorrectionNameSpec = nullptr;
268
  SmallVector<NamedDecl *, 1> CorrectionDecls;
269
  unsigned CharDistance = 0;
270
  unsigned QualifierDistance = 0;
271
  unsigned CallbackDistance = 0;
272
  SourceRange CorrectionRange;
273
  bool ForceSpecifierReplacement = false;
274
  bool RequiresImport = false;
275
276
  std::vector<PartialDiagnostic> ExtraDiagnostics;
277
};
278
279
/// Base class for callback objects used by Sema::CorrectTypo to check
280
/// the validity of a potential typo correction.
281
class CorrectionCandidateCallback {
282
public:
283
  static const unsigned InvalidDistance = TypoCorrection::InvalidDistance;
284
285
  explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr,
286
                                       NestedNameSpecifier *TypoNNS = nullptr)
287
23.5M
      : Typo(Typo), TypoNNS(TypoNNS) {}
288
289
23.5M
  virtual ~CorrectionCandidateCallback() = default;
290
291
  /// Simple predicate used by the default RankCandidate to
292
  /// determine whether to return an edit distance of 0 or InvalidDistance.
293
  /// This can be overridden by validators that only need to determine if a
294
  /// candidate is viable, without ranking potentially viable candidates.
295
  /// Only ValidateCandidate or RankCandidate need to be overridden by a
296
  /// callback wishing to check the viability of correction candidates.
297
  /// The default predicate always returns true if the candidate is not a type
298
  /// name or keyword, true for types if WantTypeSpecifiers is true, and true
299
  /// for keywords if WantTypeSpecifiers, WantExpressionKeywords,
300
  /// WantCXXNamedCasts, WantRemainingKeywords, or WantObjCSuper is true.
301
  virtual bool ValidateCandidate(const TypoCorrection &candidate);
302
303
  /// Method used by Sema::CorrectTypo to assign an "edit distance" rank
304
  /// to a candidate (where a lower value represents a better candidate), or
305
  /// returning InvalidDistance if the candidate is not at all viable. For
306
  /// validation callbacks that only need to determine if a candidate is viable,
307
  /// the default RankCandidate returns either 0 or InvalidDistance depending
308
  /// whether ValidateCandidate returns true or false.
309
3.33k
  virtual unsigned RankCandidate(const TypoCorrection &candidate) {
310
3.33k
    return (!MatchesTypo(candidate) && 
ValidateCandidate(candidate)3.33k
)
311
3.33k
               ? 
01.93k
312
3.33k
               : 
InvalidDistance1.40k
;
313
3.33k
  }
314
315
  /// Clone this CorrectionCandidateCallback. CorrectionCandidateCallbacks are
316
  /// initially stack-allocated. However in case where delayed typo-correction
317
  /// is done we need to move the callback to storage with a longer lifetime.
318
  /// Every class deriving from CorrectionCandidateCallback must implement
319
  /// this method.
320
  virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0;
321
322
2.34k
  void setTypoName(IdentifierInfo *II) { Typo = II; }
323
0
  void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }
324
325
  // Flags for context-dependent keywords. WantFunctionLikeCasts is only
326
  // used/meaningful when WantCXXNamedCasts is false.
327
  // TODO: Expand these to apply to non-keywords or possibly remove them.
328
  bool WantTypeSpecifiers = true;
329
  bool WantExpressionKeywords = true;
330
  bool WantCXXNamedCasts = true;
331
  bool WantFunctionLikeCasts = true;
332
  bool WantRemainingKeywords = true;
333
  bool WantObjCSuper = false;
334
  // Temporary hack for the one case where a CorrectTypoContext enum is used
335
  // when looking up results.
336
  bool IsObjCIvarLookup = false;
337
  bool IsAddressOfOperand = false;
338
339
protected:
340
3.33k
  bool MatchesTypo(const TypoCorrection &candidate) {
341
3.33k
    return Typo && 
candidate.isResolved()478
&&
!candidate.requiresImport()470
&&
342
3.33k
           
candidate.getCorrectionAsIdentifierInfo() == Typo412
&&
343
3.33k
           // FIXME: This probably does not return true when both
344
3.33k
           // NestedNameSpecifiers have the same textual representation.
345
3.33k
           
candidate.getCorrectionSpecifier() == TypoNNS165
;
346
3.33k
  }
347
348
  IdentifierInfo *Typo;
349
  NestedNameSpecifier *TypoNNS;
350
};
351
352
class DefaultFilterCCC final : public CorrectionCandidateCallback {
353
public:
354
  explicit DefaultFilterCCC(IdentifierInfo *Typo = nullptr,
355
                            NestedNameSpecifier *TypoNNS = nullptr)
356
11.7k
      : CorrectionCandidateCallback(Typo, TypoNNS) {}
357
358
137
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
359
137
    return llvm::make_unique<DefaultFilterCCC>(*this);
360
137
  }
361
};
362
363
/// Simple template class for restricting typo correction candidates
364
/// to ones having a single Decl* of the given type.
365
template <class C>
366
class DeclFilterCCC final : public CorrectionCandidateCallback {
367
public:
368
114
  bool ValidateCandidate(const TypoCorrection &candidate) override {
369
114
    return candidate.getCorrectionDeclAs<C>();
370
114
  }
clang::DeclFilterCCC<clang::ObjCInterfaceDecl>::ValidateCandidate(clang::TypoCorrection const&)
Line
Count
Source
368
1
  bool ValidateCandidate(const TypoCorrection &candidate) override {
369
1
    return candidate.getCorrectionDeclAs<C>();
370
1
  }
clang::DeclFilterCCC<clang::FunctionDecl>::ValidateCandidate(clang::TypoCorrection const&)
Line
Count
Source
368
79
  bool ValidateCandidate(const TypoCorrection &candidate) override {
369
79
    return candidate.getCorrectionDeclAs<C>();
370
79
  }
clang::DeclFilterCCC<clang::ObjCProtocolDecl>::ValidateCandidate(clang::TypoCorrection const&)
Line
Count
Source
368
1
  bool ValidateCandidate(const TypoCorrection &candidate) override {
369
1
    return candidate.getCorrectionDeclAs<C>();
370
1
  }
clang::DeclFilterCCC<clang::ObjCIvarDecl>::ValidateCandidate(clang::TypoCorrection const&)
Line
Count
Source
368
13
  bool ValidateCandidate(const TypoCorrection &candidate) override {
369
13
    return candidate.getCorrectionDeclAs<C>();
370
13
  }
clang::DeclFilterCCC<clang::ObjCPropertyDecl>::ValidateCandidate(clang::TypoCorrection const&)
Line
Count
Source
368
19
  bool ValidateCandidate(const TypoCorrection &candidate) override {
369
19
    return candidate.getCorrectionDeclAs<C>();
370
19
  }
clang::DeclFilterCCC<clang::VarDecl>::ValidateCandidate(clang::TypoCorrection const&)
Line
Count
Source
368
1
  bool ValidateCandidate(const TypoCorrection &candidate) override {
369
1
    return candidate.getCorrectionDeclAs<C>();
370
1
  }
371
155
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
372
155
    return llvm::make_unique<DeclFilterCCC>(*this);
373
155
  }
clang::DeclFilterCCC<clang::ObjCInterfaceDecl>::clone()
Line
Count
Source
371
31
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
372
31
    return llvm::make_unique<DeclFilterCCC>(*this);
373
31
  }
clang::DeclFilterCCC<clang::FunctionDecl>::clone()
Line
Count
Source
371
80
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
372
80
    return llvm::make_unique<DeclFilterCCC>(*this);
373
80
  }
clang::DeclFilterCCC<clang::ObjCProtocolDecl>::clone()
Line
Count
Source
371
2
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
372
2
    return llvm::make_unique<DeclFilterCCC>(*this);
373
2
  }
clang::DeclFilterCCC<clang::ObjCIvarDecl>::clone()
Line
Count
Source
371
17
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
372
17
    return llvm::make_unique<DeclFilterCCC>(*this);
373
17
  }
clang::DeclFilterCCC<clang::ObjCPropertyDecl>::clone()
Line
Count
Source
371
24
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
372
24
    return llvm::make_unique<DeclFilterCCC>(*this);
373
24
  }
clang::DeclFilterCCC<clang::VarDecl>::clone()
Line
Count
Source
371
1
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
372
1
    return llvm::make_unique<DeclFilterCCC>(*this);
373
1
  }
374
};
375
376
// Callback class to limit the allowed keywords and to only accept typo
377
// corrections that are keywords or whose decls refer to functions (or template
378
// functions) that accept the given number of arguments.
379
class FunctionCallFilterCCC : public CorrectionCandidateCallback {
380
public:
381
  FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
382
                        bool HasExplicitTemplateArgs,
383
                        MemberExpr *ME = nullptr);
384
385
  bool ValidateCandidate(const TypoCorrection &candidate) override;
386
233
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
387
233
    return llvm::make_unique<FunctionCallFilterCCC>(*this);
388
233
  }
389
390
private:
391
  unsigned NumArgs;
392
  bool HasExplicitTemplateArgs;
393
  DeclContext *CurContext;
394
  MemberExpr *MemberFn;
395
};
396
397
// Callback class that effectively disabled typo correction
398
class NoTypoCorrectionCCC final : public CorrectionCandidateCallback {
399
public:
400
1.66k
  NoTypoCorrectionCCC() {
401
1.66k
    WantTypeSpecifiers = false;
402
1.66k
    WantExpressionKeywords = false;
403
1.66k
    WantCXXNamedCasts = false;
404
1.66k
    WantFunctionLikeCasts = false;
405
1.66k
    WantRemainingKeywords = false;
406
1.66k
  }
407
408
0
  bool ValidateCandidate(const TypoCorrection &candidate) override {
409
0
    return false;
410
0
  }
411
0
  std::unique_ptr<CorrectionCandidateCallback> clone() override {
412
0
    return llvm::make_unique<NoTypoCorrectionCCC>(*this);
413
0
  }
414
};
415
416
} // namespace clang
417
418
#endif // LLVM_CLANG_SEMA_TYPOCORRECTION_H