clang 23.0.0git
FixitUtil.cpp
Go to the documentation of this file.
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
11
12using namespace llvm;
13using namespace clang;
14using 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`.
21std::optional<std::string>
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
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
93 std::optional<StringRef> RangeText =
94 getRangeText({PteTyLoc.getBeginLoc(), PteEndOfTokenLoc}, SM, LangOpts);
95 if (!RangeText)
96 return std::nullopt;
97 return RangeText->str();
98}
99
100// returns text of pointee to pointee (T*&)
101std::optional<std::string>
103 const LangOptions &LangOpts,
104 std::optional<Qualifiers> *QualifiersToAppend) {
105
106 QualType Ty = VD->getType();
107 assert(Ty->isReferenceType() &&
108 "Expecting a VarDecl of reference to pointer type");
109
110 Ty = Ty->getPointeeType();
111 QualType PteTy;
112
113 assert(Ty->isPointerType() && !Ty->isFunctionPointerType() &&
114 "Expecting a VarDecl of type of pointer to object type");
115 PteTy = Ty->getPointeeType();
116
118 TypeLoc PtrTyLoc;
119 TypeLoc PteTyLoc;
120
121 // We only deal with the cases that we know `TypeLoc::getNextTypeLoc` returns
122 // the `TypeLoc` of the pointee type:
123 switch (TyLoc.getTypeLocClass()) {
124 case TypeLoc::ConstantArray:
125 case TypeLoc::IncompleteArray:
126 case TypeLoc::VariableArray:
127 case TypeLoc::DependentSizedArray:
128 case TypeLoc::LValueReference:
129 PtrTyLoc = TyLoc.castAs<ReferenceTypeLoc>().getPointeeLoc();
130 if (PtrTyLoc.getTypeLocClass() == TypeLoc::Pointer) {
131 PteTyLoc = PtrTyLoc.castAs<PointerTypeLoc>().getPointeeLoc();
132 break;
133 }
134 return std::nullopt;
135 break;
136 default:
137 return std::nullopt;
138 }
139 if (PteTyLoc.isNull())
140 // Sometimes we cannot get a useful `TypeLoc` for the pointee type, e.g.,
141 // when the pointer type is `auto`.
142 return std::nullopt;
143
144 // TODO make sure this works
145 SourceLocation IdentLoc = VD->getLocation();
146
147 if (!(IdentLoc.isValid() && PteTyLoc.getSourceRange().isValid())) {
148 // We are expecting these locations to be valid. But in some cases, they are
149 // not all valid. It is a Clang bug to me and we are not responsible for
150 // fixing it. So we will just give up for now when it happens.
151 return std::nullopt;
152 }
153
154 // Note that TypeLoc.getEndLoc() returns the begin location of the last token:
155 SourceLocation PteEndOfTokenLoc =
156 Lexer::getLocForEndOfToken(PteTyLoc.getEndLoc(), 0, SM, LangOpts);
157
158 if (!PteEndOfTokenLoc.isValid())
159 // Sometimes we cannot get the end location of the pointee type, e.g., when
160 // there are macros involved.
161 return std::nullopt;
162 if (!SM.isBeforeInTranslationUnit(PteEndOfTokenLoc, IdentLoc)) {
163 // We only deal with the cases where the source text of the pointee type
164 // appears on the left-hand side of the variable identifier completely,
165 // including the following forms:
166 // `T ident`,
167 // `T ident[]`, where `T` is any type.
168 // Examples of excluded cases are `T (*ident)[]` or `T ident[][n]`.
169 return std::nullopt;
170 }
171 if (PteTy.hasQualifiers()) {
172 // TypeLoc does not provide source ranges for qualifiers (it says it's
173 // intentional but seems fishy to me), so we cannot get the full text
174 // `PteTy` via source ranges.
175 *QualifiersToAppend = PteTy.getQualifiers();
176 }
177 return getRangeText({PteTyLoc.getBeginLoc(), PteEndOfTokenLoc}, SM, LangOpts)
178 ->str();
179}
180
187
188// Returns the literal text in `SourceRange SR`, if `SR` is a valid range.
189std::optional<StringRef> clang::getRangeText(SourceRange SR,
190 const SourceManager &SM,
191 const LangOptions &LangOpts) {
192 bool Invalid = false;
194 StringRef Text = Lexer::getSourceText(CSR, SM, LangOpts, &Invalid);
195
196 if (!Invalid)
197 return Text;
198 return std::nullopt;
199}
200
201// Returns the literal text of the identifier of the given variable declaration.
202std::optional<StringRef>
204 const SourceManager &SM,
205 const LangOptions &LangOpts) {
206 SourceLocation ParmIdentBeginLoc = getBeginLocOfNestedIdentifier(VD);
207 SourceLocation ParmIdentEndLoc =
209
210 if (VD->getQualifier()) {
211 ParmIdentBeginLoc = VD->getQualifierLoc().getBeginLoc();
212 }
213
214 if (ParmIdentEndLoc.isMacroID() &&
215 !Lexer::isAtEndOfMacroExpansion(ParmIdentEndLoc, SM, LangOpts))
216 return std::nullopt;
217 return getRangeText({ParmIdentBeginLoc, ParmIdentEndLoc}, SM, LangOpts);
218}
219
220// Return text representation of an `Expr`.
221std::optional<StringRef> clang::getExprText(const Expr *E,
222 const SourceManager &SM,
223 const LangOptions &LangOpts) {
224 std::optional<SourceLocation> LastCharLoc = getPastLoc(E, SM, LangOpts);
225
226 if (LastCharLoc)
228 CharSourceRange::getCharRange(E->getBeginLoc(), *LastCharLoc), SM,
229 LangOpts);
230
231 return std::nullopt;
232}
233
234// Returns the begin location of the identifier of the given variable
235// declaration.
237 // According to the implementation of `VarDecl`, `VD->getLocation()` actually
238 // returns the begin location of the identifier of the declaration:
239 return VD->getLocation();
240}
#define SM(sm)
Represents a byte-granular source range.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getLocation() const
Definition DeclBase.h:439
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:780
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition Decl.h:845
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name of this declaration, if it was present in ...
Definition Decl.h:837
TypeSourceInfo * getTypeSourceInfo() const
Definition Decl.h:809
This represents one expression.
Definition Expr.h:112
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
Definition Lexer.cpp:1030
static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd=nullptr)
Returns true if the given MacroID location points at the last token of the macro expansion.
Definition Lexer.cpp:902
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
Definition Lexer.cpp:858
SourceLocation getBeginLoc() const
Retrieve the location of the beginning of this nested-name-specifier.
Wrapper for source info for pointers.
Definition TypeLoc.h:1513
A (possibly-)qualified type.
Definition TypeBase.h:937
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8477
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8428
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
UnqualTypeLoc getUnqualifiedLoc() const
Skips past any qualifiers, if this is qualified.
Definition TypeLoc.h:349
TypeLoc getNextTypeLoc() const
Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the TypeLoc is a PointerLoc and next Typ...
Definition TypeLoc.h:171
T castAs() const
Convert to the specified TypeLoc type, asserting that this TypeLoc is of the desired type.
Definition TypeLoc.h:78
SourceRange getSourceRange() const LLVM_READONLY
Get the full source range.
Definition TypeLoc.h:154
TypeLocClass getTypeLocClass() const
Definition TypeLoc.h:116
bool isNull() const
Definition TypeLoc.h:121
SourceLocation getEndLoc() const
Get the end source location.
Definition TypeLoc.cpp:227
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:267
bool isFunctionPointerType() const
Definition TypeBase.h:8692
bool isPointerType() const
Definition TypeBase.h:8625
bool isReferenceType() const
Definition TypeBase.h:8649
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:753
QualType getType() const
Definition Decl.h:723
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
SourceLocation getVarDeclIdentifierLoc(const DeclaratorDecl *VD)
SourceLocation getBeginLocOfNestedIdentifier(const DeclaratorDecl *D)
std::optional< StringRef > getExprText(const Expr *E, const SourceManager &SM, const LangOptions &LangOpts)
std::optional< std::string > getPointeeTypeText(const DeclaratorDecl *VD, const SourceManager &SM, const LangOptions &LangOpts, std::optional< Qualifiers > *QualifiersToAppend)
Definition FixitUtil.cpp:22
std::optional< std::string > getPointee2TypeText(const DeclaratorDecl *VD, const SourceManager &SM, const LangOptions &LangOpts, std::optional< Qualifiers > *QualifiersToAppend)
std::optional< StringRef > getRangeText(SourceRange SR, const SourceManager &SM, const LangOptions &LangOpts)
std::optional< StringRef > getVarDeclIdentifierText(const DeclaratorDecl *VD, const SourceManager &SM, const LangOptions &LangOpts)
std::optional< SourceLocation > getPastLoc(const NodeTy *Node, const SourceManager &SM, const LangOptions &LangOpts)
Definition FixitUtil.h:54
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30