Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Tooling/Core/Lookup.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Lookup.cpp - Framework for clang refactoring tools ---------------===//
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 helper methods for clang tools performing name lookup.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/Tooling/Core/Lookup.h"
14
#include "clang/AST/Decl.h"
15
#include "clang/AST/DeclCXX.h"
16
#include "clang/AST/DeclarationName.h"
17
#include "clang/Basic/SourceLocation.h"
18
#include "llvm/ADT/SmallVector.h"
19
using namespace clang;
20
using namespace clang::tooling;
21
22
// Gets all namespaces that \p Context is in as a vector (ignoring anonymous
23
// namespaces). The inner namespaces come before outer namespaces in the vector.
24
// For example, if the context is in the following namespace:
25
//    `namespace a { namespace b { namespace c ( ... ) } }`,
26
// the vector will be `{c, b, a}`.
27
static llvm::SmallVector<const NamespaceDecl *, 4>
28
372
getAllNamedNamespaces(const DeclContext *Context) {
29
372
  llvm::SmallVector<const NamespaceDecl *, 4> Namespaces;
30
716
  auto GetNextNamedNamespace = [](const DeclContext *Context) {
31
716
    // Look past non-namespaces and anonymous namespaces on FromContext.
32
1.28k
    while (Context && 
(915
!isa<NamespaceDecl>(Context)915
||
33
915
                       
cast<NamespaceDecl>(Context)->isAnonymousNamespace()346
))
34
571
      Context = Context->getParent();
35
716
    return Context;
36
716
  };
37
716
  for (Context = GetNextNamedNamespace(Context); Context != nullptr;
38
372
       
Context = GetNextNamedNamespace(Context->getParent())344
)
39
344
    Namespaces.push_back(cast<NamespaceDecl>(Context));
40
372
  return Namespaces;
41
372
}
42
43
// Returns true if the context in which the type is used and the context in
44
// which the type is declared are the same semantical namespace but different
45
// lexical namespaces.
46
static bool
47
usingFromDifferentCanonicalNamespace(const DeclContext *FromContext,
48
100
                                     const DeclContext *UseContext) {
49
100
  // We can skip anonymous namespace because:
50
100
  // 1. `FromContext` and `UseContext` must be in the same anonymous namespaces
51
100
  // since referencing across anonymous namespaces is not possible.
52
100
  // 2. If `FromContext` and `UseContext` are in the same anonymous namespace,
53
100
  // the function will still return `false` as expected.
54
100
  llvm::SmallVector<const NamespaceDecl *, 4> FromNamespaces =
55
100
      getAllNamedNamespaces(FromContext);
56
100
  llvm::SmallVector<const NamespaceDecl *, 4> UseNamespaces =
57
100
      getAllNamedNamespaces(UseContext);
58
100
  // If `UseContext` has fewer level of nested namespaces, it cannot be in the
59
100
  // same canonical namespace as the `FromContext`.
60
100
  if (UseNamespaces.size() < FromNamespaces.size())
61
4
    return false;
62
96
  unsigned Diff = UseNamespaces.size() - FromNamespaces.size();
63
96
  auto FromIter = FromNamespaces.begin();
64
96
  // Only compare `FromNamespaces` with namespaces in `UseNamespaces` that can
65
96
  // collide, i.e. the top N namespaces where N is the number of namespaces in
66
96
  // `FromNamespaces`.
67
96
  auto UseIter = UseNamespaces.begin() + Diff;
68
98
  for (; FromIter != FromNamespaces.end() && 
UseIter != UseNamespaces.end()96
;
69
96
       
++FromIter, ++UseIter2
) {
70
96
    // Literally the same namespace, not a collision.
71
96
    if (*FromIter == *UseIter)
72
62
      return false;
73
34
    // Now check the names. If they match we have a different canonical
74
34
    // namespace with the same name.
75
34
    if (cast<NamespaceDecl>(*FromIter)->getDeclName() ==
76
34
        cast<NamespaceDecl>(*UseIter)->getDeclName())
77
32
      return true;
78
34
  }
79
96
  assert(FromIter == FromNamespaces.end() && UseIter == UseNamespaces.end());
80
2
  return false;
81
96
}
82
83
static StringRef getBestNamespaceSubstr(const DeclContext *DeclA,
84
                                        StringRef NewName,
85
177
                                        bool HadLeadingColonColon) {
86
230
  while (true) {
87
497
    while (DeclA && 
!isa<NamespaceDecl>(DeclA)358
)
88
267
      DeclA = DeclA->getParent();
89
230
90
230
    // Fully qualified it is! Leave :: in place if it's there already.
91
230
    if (!DeclA)
92
139
      return HadLeadingColonColon ? 
NewName5
:
NewName.substr(2)134
;
93
91
94
91
    // Otherwise strip off redundant namespace qualifications from the new name.
95
91
    // We use the fully qualified name of the namespace and remove that part
96
91
    // from NewName if it has an identical prefix.
97
91
    std::string NS =
98
91
        "::" + cast<NamespaceDecl>(DeclA)->getQualifiedNameAsString() + "::";
99
91
    if (NewName.startswith(NS))
100
38
      return NewName.substr(NS.size());
101
53
102
53
    // No match yet. Strip of a namespace from the end of the chain and try
103
53
    // again. This allows to get optimal qualifications even if the old and new
104
53
    // decl only share common namespaces at a higher level.
105
53
    DeclA = DeclA->getParent();
106
53
  }
107
177
}
108
109
/// Check if the name specifier begins with a written "::".
110
177
static bool isFullyQualified(const NestedNameSpecifier *NNS) {
111
315
  while (NNS) {
112
146
    if (NNS->getKind() == NestedNameSpecifier::Global)
113
8
      return true;
114
138
    NNS = NNS->getPrefix();
115
138
  }
116
177
  
return false169
;
117
177
}
118
119
// Adds more scope specifier to the spelled name until the spelling is not
120
// ambiguous. A spelling is ambiguous if the resolution of the symbol is
121
// ambiguous. For example, if QName is "::y::bar", the spelling is "y::bar", and
122
// context contains a nested namespace "a::y", then "y::bar" can be resolved to
123
// ::a::y::bar in the context, which can cause compile error.
124
// FIXME: consider using namespaces.
125
static std::string disambiguateSpellingInScope(StringRef Spelling,
126
                                               StringRef QName,
127
                                               const DeclContext &UseContext,
128
177
                                               SourceLocation UseLoc) {
129
177
  assert(QName.startswith("::"));
130
177
  assert(QName.endswith(Spelling));
131
177
  if (Spelling.startswith("::"))
132
5
    return std::string(Spelling);
133
172
134
172
  auto UnspelledSpecifier = QName.drop_back(Spelling.size());
135
172
  llvm::SmallVector<llvm::StringRef, 2> UnspelledScopes;
136
172
  UnspelledSpecifier.split(UnspelledScopes, "::", /*MaxSplit=*/-1,
137
172
                           /*KeepEmpty=*/false);
138
172
139
172
  llvm::SmallVector<const NamespaceDecl *, 4> EnclosingNamespaces =
140
172
      getAllNamedNamespaces(&UseContext);
141
172
  auto &AST = UseContext.getParentASTContext();
142
172
  StringRef TrimmedQName = QName.substr(2);
143
172
  const auto &SM = UseContext.getParentASTContext().getSourceManager();
144
172
  UseLoc = SM.getSpellingLoc(UseLoc);
145
172
146
175
  auto IsAmbiguousSpelling = [&](const llvm::StringRef CurSpelling) {
147
175
    if (CurSpelling.startswith("::"))
148
2
      return false;
149
173
    // Lookup the first component of Spelling in all enclosing namespaces
150
173
    // and check if there is any existing symbols with the same name but in
151
173
    // different scope.
152
173
    StringRef Head = CurSpelling.split("::").first;
153
173
    for (const auto *NS : EnclosingNamespaces) {
154
97
      auto LookupRes = NS->lookup(DeclarationName(&AST.Idents.get(Head)));
155
97
      if (!LookupRes.empty()) {
156
4
        for (const NamedDecl *Res : LookupRes)
157
4
          // If `Res` is not visible in `UseLoc`, we don't consider it
158
4
          // ambiguous. For example, a reference in a header file should not be
159
4
          // affected by a potentially ambiguous name in some file that includes
160
4
          // the header.
161
4
          if (!TrimmedQName.startswith(Res->getQualifiedNameAsString()) &&
162
4
              SM.isBeforeInTranslationUnit(
163
4
                  SM.getSpellingLoc(Res->getLocation()), UseLoc))
164
3
            return true;
165
4
      }
166
97
    }
167
173
    
return false170
;
168
173
  };
169
172
170
172
  // Add more qualifiers until the spelling is not ambiguous.
171
172
  std::string Disambiguated = std::string(Spelling);
172
175
  while (IsAmbiguousSpelling(Disambiguated)) {
173
3
    if (UnspelledScopes.empty()) {
174
2
      Disambiguated = "::" + Disambiguated;
175
2
    } else {
176
1
      Disambiguated = (UnspelledScopes.back() + "::" + Disambiguated).str();
177
1
      UnspelledScopes.pop_back();
178
1
    }
179
3
  }
180
172
  return Disambiguated;
181
172
}
182
183
std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
184
                                       SourceLocation UseLoc,
185
                                       const DeclContext *UseContext,
186
                                       const NamedDecl *FromDecl,
187
245
                                       StringRef ReplacementString) {
188
245
  assert(ReplacementString.startswith("::") &&
189
245
         "Expected fully-qualified name!");
190
245
191
245
  // We can do a raw name replacement when we are not inside the namespace for
192
245
  // the original class/function and it is not in the global namespace.  The
193
245
  // assumption is that outside the original namespace we must have a using
194
245
  // statement that makes this work out and that other parts of this refactor
195
245
  // will automatically fix using statements to point to the new class/function.
196
245
  // However, if the `FromDecl` is a class forward declaration, the reference is
197
245
  // still considered as referring to the original definition, so we can't do a
198
245
  // raw name replacement in this case.
199
245
  const bool class_name_only = !Use;
200
245
  const bool in_global_namespace =
201
245
      isa<TranslationUnitDecl>(FromDecl->getDeclContext());
202
245
  const bool is_class_forward_decl =
203
245
      isa<CXXRecordDecl>(FromDecl) &&
204
245
      
!cast<CXXRecordDecl>(FromDecl)->isCompleteDefinition()140
;
205
245
  if (class_name_only && 
!in_global_namespace121
&&
!is_class_forward_decl102
&&
206
245
      !usingFromDifferentCanonicalNamespace(FromDecl->getDeclContext(),
207
100
                                            UseContext)) {
208
68
    auto Pos = ReplacementString.rfind("::");
209
68
    return std::string(Pos != StringRef::npos
210
68
                           ? ReplacementString.substr(Pos + 2)
211
68
                           : 
ReplacementString0
);
212
68
  }
213
177
  // We did not match this because of a using statement, so we will need to
214
177
  // figure out how good a namespace match we have with our destination type.
215
177
  // We work backwards (from most specific possible namespace to least
216
177
  // specific).
217
177
  StringRef Suggested = getBestNamespaceSubstr(UseContext, ReplacementString,
218
177
                                               isFullyQualified(Use));
219
177
220
177
  return disambiguateSpellingInScope(Suggested, ReplacementString, *UseContext,
221
177
                                     UseLoc);
222
177
}