clang: lib/Tooling/Refactoring/Lookup.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

20#include "llvm/ADT/SmallVector.h"

21using namespace clang;

23

24

25

26

27

28

32 auto GetNextNamedNamespace = [](const DeclContext *Context) {

33

34 while (Context && (!isa(Context) ||

35 cast(Context)->isAnonymousNamespace()))

36 Context = Context->getParent();

37 return Context;

38 };

39 for (Context = GetNextNamedNamespace(Context); Context != nullptr;

40 Context = GetNextNamedNamespace(Context->getParent()))

41 Namespaces.push_back(cast(Context));

42 return Namespaces;

43}

44

45

46

47

48static bool

51

52

53

54

55

60

61

62 if (UseNamespaces.size() < FromNamespaces.size())

63 return false;

64 unsigned Diff = UseNamespaces.size() - FromNamespaces.size();

65 auto FromIter = FromNamespaces.begin();

66

67

68

69 auto UseIter = UseNamespaces.begin() + Diff;

70 for (; FromIter != FromNamespaces.end() && UseIter != UseNamespaces.end();

71 ++FromIter, ++UseIter) {

72

73 if (*FromIter == *UseIter)

74 return false;

75

76

77 if (cast(*FromIter)->getDeclName() ==

78 cast(*UseIter)->getDeclName())

79 return true;

80 }

81 assert(FromIter == FromNamespaces.end() && UseIter == UseNamespaces.end());

82 return false;

83}

84

86 StringRef NewName,

87 bool HadLeadingColonColon) {

88 while (true) {

89 while (DeclA && !isa(DeclA))

91

92

93 if (!DeclA)

94 return HadLeadingColonColon ? NewName : NewName.substr(2);

95

96

97

98

99 std::string NS =

100 "::" + cast(DeclA)->getQualifiedNameAsString() + "::";

101 if (NewName.consume_front(NS))

102 return NewName;

103

104

105

106

108 }

109}

110

111

113 while (NNS) {

115 return true;

117 }

118 return false;

119}

120

121

122

123

124

125

126

128 StringRef QName,

131 assert(QName.starts_with("::"));

132 assert(QName.ends_with(Spelling));

133 if (Spelling.starts_with("::"))

134 return std::string(Spelling);

135

136 auto UnspelledSpecifier = QName.drop_back(Spelling.size());

138 UnspelledSpecifier.split(UnspelledScopes, "::", -1,

139 false);

140

144 StringRef TrimmedQName = QName.substr(2);

146 UseLoc = SM.getSpellingLoc(UseLoc);

147

148 auto IsAmbiguousSpelling = [&](const llvm::StringRef CurSpelling) {

149 if (CurSpelling.starts_with("::"))

150 return false;

151

152

153

154 StringRef Head = CurSpelling.split("::").first;

155 for (const auto *NS : EnclosingNamespaces) {

156 auto LookupRes = NS->lookup(DeclarationName(&AST.Idents.get(Head)));

157 if (!LookupRes.empty()) {

158 for (const NamedDecl *Res : LookupRes)

159

160

161

162

163 if (!TrimmedQName.starts_with(Res->getQualifiedNameAsString()) &&

164 SM.isBeforeInTranslationUnit(

165 SM.getSpellingLoc(Res->getLocation()), UseLoc))

166 return true;

167 }

168 }

169 return false;

170 };

171

172

173 std::string Disambiguated = std::string(Spelling);

174 while (IsAmbiguousSpelling(Disambiguated)) {

175 if (UnspelledScopes.empty()) {

176 Disambiguated = "::" + Disambiguated;

177 } else {

178 Disambiguated = (UnspelledScopes.back() + "::" + Disambiguated).str();

179 UnspelledScopes.pop_back();

180 }

181 }

182 return Disambiguated;

183}

184

189 StringRef ReplacementString) {

190 assert(ReplacementString.starts_with("::") &&

191 "Expected fully-qualified name!");

192

193

194

195

196

197

198

199

200

201 const bool class_name_only = !Use;

202 const bool in_global_namespace =

204 const bool is_class_forward_decl =

205 isa(FromDecl) &&

206 !cast(FromDecl)->isCompleteDefinition();

207 if (class_name_only && !in_global_namespace && !is_class_forward_decl &&

209 UseContext)) {

210 auto Pos = ReplacementString.rfind("::");

211 return std::string(Pos != StringRef::npos

212 ? ReplacementString.substr(Pos + 2)

213 : ReplacementString);

214 }

215

216

217

218

221

223 UseLoc);

224}

Defines the clang::ASTContext interface.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

static llvm::SmallVector< const NamespaceDecl *, 4 > getAllNamedNamespaces(const DeclContext *Context)

static bool usingFromDifferentCanonicalNamespace(const DeclContext *FromContext, const DeclContext *UseContext)

static StringRef getBestNamespaceSubstr(const DeclContext *DeclA, StringRef NewName, bool HadLeadingColonColon)

static std::string disambiguateSpellingInScope(StringRef Spelling, StringRef QName, const DeclContext &UseContext, SourceLocation UseLoc)

static bool isFullyQualified(const NestedNameSpecifier *NNS)

Check if the name specifier begins with a written "::".

Defines the clang::SourceLocation class and associated facilities.

Defines the SourceManager interface.

const NamedDecl * FromDecl

SourceManager & getSourceManager()

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

DeclContext * getParent()

getParent - Returns the containing DeclContext.

ASTContext & getParentASTContext() const

DeclContext * getDeclContext()

The name of a declaration.

This represents a decl that may have a name.

Represents a C++ nested name specifier, such as "\::std::vector::".

SpecifierKind getKind() const

Determine what kind of nested name specifier is stored.

NestedNameSpecifier * getPrefix() const

Return the prefix of this nested name specifier.

@ Global

The global specifier '::'. There is no stored value.

Encodes a location in the source.

The JSON file list parser is used to communicate input to InstallAPI.