Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Analysis/FixitUtil.cpp
213766 views
1
//===- FixitUtil.cpp ------------------------------------------------------===//
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
#include "clang/Analysis/Support/FixitUtil.h"
10
#include "clang/ASTMatchers/ASTMatchers.h"
11
12
using namespace llvm;
13
using namespace clang;
14
using namespace ast_matchers;
15
16
// Returns the text of the pointee type of `T` from a `VarDecl` of a pointer
17
// type. The text is obtained through from `TypeLoc`s. Since `TypeLoc` does not
18
// have source ranges of qualifiers ( The `QualTypeLoc` looks hacky too me
19
// :( ), `Qualifiers` of the pointee type is returned separately through the
20
// output parameter `QualifiersToAppend`.
21
std::optional<std::string>
22
clang::getPointeeTypeText(const DeclaratorDecl *VD, const SourceManager &SM,
23
const LangOptions &LangOpts,
24
std::optional<Qualifiers> *QualifiersToAppend) {
25
QualType Ty = VD->getType();
26
QualType PteTy;
27
28
assert(Ty->isPointerType() && !Ty->isFunctionPointerType() &&
29
"Expecting a VarDecl of type of pointer to object type");
30
PteTy = Ty->getPointeeType();
31
32
TypeLoc TyLoc = VD->getTypeSourceInfo()->getTypeLoc().getUnqualifiedLoc();
33
TypeLoc PteTyLoc;
34
35
// We only deal with the cases that we know `TypeLoc::getNextTypeLoc` returns
36
// the `TypeLoc` of the pointee type:
37
switch (TyLoc.getTypeLocClass()) {
38
case TypeLoc::ConstantArray:
39
case TypeLoc::IncompleteArray:
40
case TypeLoc::VariableArray:
41
case TypeLoc::DependentSizedArray:
42
case TypeLoc::Decayed:
43
assert(isa<ParmVarDecl>(VD) && "An array type shall not be treated as a "
44
"pointer type unless it decays.");
45
PteTyLoc = TyLoc.getNextTypeLoc();
46
break;
47
case TypeLoc::Pointer:
48
PteTyLoc = TyLoc.castAs<PointerTypeLoc>().getPointeeLoc();
49
break;
50
default:
51
return std::nullopt;
52
}
53
if (PteTyLoc.isNull())
54
// Sometimes we cannot get a useful `TypeLoc` for the pointee type, e.g.,
55
// when the pointer type is `auto`.
56
return std::nullopt;
57
58
// TODO check
59
SourceLocation IdentLoc = VD->getLocation();
60
61
if (!(IdentLoc.isValid() && PteTyLoc.getSourceRange().isValid())) {
62
// We are expecting these locations to be valid. But in some cases, they are
63
// not all valid. It is a Clang bug to me and we are not responsible for
64
// fixing it. So we will just give up for now when it happens.
65
return std::nullopt;
66
}
67
68
// Note that TypeLoc.getEndLoc() returns the begin location of the last token:
69
SourceLocation PteEndOfTokenLoc =
70
Lexer::getLocForEndOfToken(PteTyLoc.getEndLoc(), 0, SM, LangOpts);
71
72
if (!PteEndOfTokenLoc.isValid())
73
// Sometimes we cannot get the end location of the pointee type, e.g., when
74
// there are macros involved.
75
return std::nullopt;
76
if (!SM.isBeforeInTranslationUnit(PteEndOfTokenLoc, IdentLoc) &&
77
PteEndOfTokenLoc != IdentLoc) {
78
// We only deal with the cases where the source text of the pointee type
79
// appears on the left-hand side of the variable identifier completely,
80
// including the following forms:
81
// `T ident`,
82
// `T ident[]`, where `T` is any type.
83
// Examples of excluded cases are `T (*ident)[]` or `T ident[][n]`.
84
return std::nullopt;
85
}
86
if (PteTy.hasQualifiers()) {
87
// TypeLoc does not provide source ranges for qualifiers (it says it's
88
// intentional but seems fishy to me), so we cannot get the full text
89
// `PteTy` via source ranges.
90
*QualifiersToAppend = PteTy.getQualifiers();
91
}
92
return getRangeText({PteTyLoc.getBeginLoc(), PteEndOfTokenLoc}, SM, LangOpts)
93
->str();
94
}
95
96
// returns text of pointee to pointee (T*&)
97
std::optional<std::string>
98
getPointee2TypeText(const DeclaratorDecl *VD, const SourceManager &SM,
99
const LangOptions &LangOpts,
100
std::optional<Qualifiers> *QualifiersToAppend) {
101
102
QualType Ty = VD->getType();
103
assert(Ty->isReferenceType() &&
104
"Expecting a VarDecl of reference to pointer type");
105
106
Ty = Ty->getPointeeType();
107
QualType PteTy;
108
109
assert(Ty->isPointerType() && !Ty->isFunctionPointerType() &&
110
"Expecting a VarDecl of type of pointer to object type");
111
PteTy = Ty->getPointeeType();
112
113
TypeLoc TyLoc = VD->getTypeSourceInfo()->getTypeLoc().getUnqualifiedLoc();
114
TypeLoc PtrTyLoc;
115
TypeLoc PteTyLoc;
116
117
// We only deal with the cases that we know `TypeLoc::getNextTypeLoc` returns
118
// the `TypeLoc` of the pointee type:
119
switch (TyLoc.getTypeLocClass()) {
120
case TypeLoc::ConstantArray:
121
case TypeLoc::IncompleteArray:
122
case TypeLoc::VariableArray:
123
case TypeLoc::DependentSizedArray:
124
case TypeLoc::LValueReference:
125
PtrTyLoc = TyLoc.castAs<ReferenceTypeLoc>().getPointeeLoc();
126
if (PtrTyLoc.getTypeLocClass() == TypeLoc::Pointer) {
127
PteTyLoc = PtrTyLoc.castAs<PointerTypeLoc>().getPointeeLoc();
128
break;
129
}
130
return std::nullopt;
131
break;
132
default:
133
return std::nullopt;
134
}
135
if (PteTyLoc.isNull())
136
// Sometimes we cannot get a useful `TypeLoc` for the pointee type, e.g.,
137
// when the pointer type is `auto`.
138
return std::nullopt;
139
140
// TODO make sure this works
141
SourceLocation IdentLoc = VD->getLocation();
142
143
if (!(IdentLoc.isValid() && PteTyLoc.getSourceRange().isValid())) {
144
// We are expecting these locations to be valid. But in some cases, they are
145
// not all valid. It is a Clang bug to me and we are not responsible for
146
// fixing it. So we will just give up for now when it happens.
147
return std::nullopt;
148
}
149
150
// Note that TypeLoc.getEndLoc() returns the begin location of the last token:
151
SourceLocation PteEndOfTokenLoc =
152
Lexer::getLocForEndOfToken(PteTyLoc.getEndLoc(), 0, SM, LangOpts);
153
154
if (!PteEndOfTokenLoc.isValid())
155
// Sometimes we cannot get the end location of the pointee type, e.g., when
156
// there are macros involved.
157
return std::nullopt;
158
if (!SM.isBeforeInTranslationUnit(PteEndOfTokenLoc, IdentLoc)) {
159
// We only deal with the cases where the source text of the pointee type
160
// appears on the left-hand side of the variable identifier completely,
161
// including the following forms:
162
// `T ident`,
163
// `T ident[]`, where `T` is any type.
164
// Examples of excluded cases are `T (*ident)[]` or `T ident[][n]`.
165
return std::nullopt;
166
}
167
if (PteTy.hasQualifiers()) {
168
// TypeLoc does not provide source ranges for qualifiers (it says it's
169
// intentional but seems fishy to me), so we cannot get the full text
170
// `PteTy` via source ranges.
171
*QualifiersToAppend = PteTy.getQualifiers();
172
}
173
return getRangeText({PteTyLoc.getBeginLoc(), PteEndOfTokenLoc}, SM, LangOpts)
174
->str();
175
}
176
177
SourceLocation clang::getBeginLocOfNestedIdentifier(const DeclaratorDecl *D) {
178
if (D->getQualifier()) {
179
return D->getQualifierLoc().getBeginLoc();
180
}
181
return getVarDeclIdentifierLoc(D);
182
}
183
184
// Returns the literal text in `SourceRange SR`, if `SR` is a valid range.
185
std::optional<StringRef> clang::getRangeText(SourceRange SR,
186
const SourceManager &SM,
187
const LangOptions &LangOpts) {
188
bool Invalid = false;
189
CharSourceRange CSR = CharSourceRange::getCharRange(SR);
190
StringRef Text = Lexer::getSourceText(CSR, SM, LangOpts, &Invalid);
191
192
if (!Invalid)
193
return Text;
194
return std::nullopt;
195
}
196
197
// Returns the literal text of the identifier of the given variable declaration.
198
std::optional<StringRef>
199
clang::getVarDeclIdentifierText(const DeclaratorDecl *VD,
200
const SourceManager &SM,
201
const LangOptions &LangOpts) {
202
SourceLocation ParmIdentBeginLoc = getBeginLocOfNestedIdentifier(VD);
203
SourceLocation ParmIdentEndLoc =
204
Lexer::getLocForEndOfToken(getVarDeclIdentifierLoc(VD), 0, SM, LangOpts);
205
206
if (VD->getQualifier()) {
207
ParmIdentBeginLoc = VD->getQualifierLoc().getBeginLoc();
208
}
209
210
if (ParmIdentEndLoc.isMacroID() &&
211
!Lexer::isAtEndOfMacroExpansion(ParmIdentEndLoc, SM, LangOpts))
212
return std::nullopt;
213
return getRangeText({ParmIdentBeginLoc, ParmIdentEndLoc}, SM, LangOpts);
214
}
215
216
// Return text representation of an `Expr`.
217
std::optional<StringRef> clang::getExprText(const Expr *E,
218
const SourceManager &SM,
219
const LangOptions &LangOpts) {
220
std::optional<SourceLocation> LastCharLoc = getPastLoc(E, SM, LangOpts);
221
222
if (LastCharLoc)
223
return Lexer::getSourceText(
224
CharSourceRange::getCharRange(E->getBeginLoc(), *LastCharLoc), SM,
225
LangOpts);
226
227
return std::nullopt;
228
}
229
230
// Returns the begin location of the identifier of the given variable
231
// declaration.
232
SourceLocation clang::getVarDeclIdentifierLoc(const DeclaratorDecl *VD) {
233
// According to the implementation of `VarDecl`, `VD->getLocation()` actually
234
// returns the begin location of the identifier of the declaration:
235
return VD->getLocation();
236
}
237
238