clang 22.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 return getRangeText({PteTyLoc.getBeginLoc(), PteEndOfTokenLoc}, SM, LangOpts)
93 ->str();
94}
95
96// returns text of pointee to pointee (T*&)
97std::optional<std::string>
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
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
178 if (D->getQualifier()) {
179 return D->getQualifierLoc().getBeginLoc();
180 }
182}
183
184// Returns the literal text in `SourceRange SR`, if `SR` is a valid range.
185std::optional<StringRef> clang::getRangeText(SourceRange SR,
186 const SourceManager &SM,
187 const LangOptions &LangOpts) {
188 bool Invalid = false;
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.
198std::optional<StringRef>
200 const SourceManager &SM,
201 const LangOptions &LangOpts) {
202 SourceLocation ParmIdentBeginLoc = getBeginLocOfNestedIdentifier(VD);
203 SourceLocation ParmIdentEndLoc =
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`.
217std::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)
225 LangOpts);
226
227 return std::nullopt;
228}
229
230// Returns the begin location of the identifier of the given variable
231// declaration.
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}
const Decl * D
Expr * E
std::optional< std::string > getPointee2TypeText(const DeclaratorDecl *VD, const SourceManager &SM, const LangOptions &LangOpts, std::optional< Qualifiers > *QualifiersToAppend)
Definition: FixitUtil.cpp:98
StringRef Text
Definition: Format.cpp:3178
#define SM(sm)
Definition: OffloadArch.cpp:16
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getLocation() const
Definition: DeclBase.h:439
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:431
Represents a ValueDecl that came out of a declarator.
Definition: Decl.h:779
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
Definition: Decl.h:844
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name of this declaration, if it was present in ...
Definition: Decl.h:836
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:808
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...
Definition: LangOptions.h:434
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:1020
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:892
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:848
SourceLocation getBeginLoc() const
Retrieve the location of the beginning of this nested-name-specifier.
Wrapper for source info for pointers.
Definition: TypeLoc.h:1493
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: TypeBase.h:8432
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: TypeBase.h:8383
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.
bool isValid() const
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
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:354
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:272
bool isFunctionPointerType() const
Definition: TypeBase.h:8647
bool isPointerType() const
Definition: TypeBase.h:8580
bool isReferenceType() const
Definition: TypeBase.h:8604
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
QualType getType() const
Definition: Decl.h:722
The JSON file list parser is used to communicate input to InstallAPI.
SourceLocation getVarDeclIdentifierLoc(const DeclaratorDecl *VD)
Definition: FixitUtil.cpp:232
SourceLocation getBeginLocOfNestedIdentifier(const DeclaratorDecl *D)
Definition: FixitUtil.cpp:177
std::optional< StringRef > getExprText(const Expr *E, const SourceManager &SM, const LangOptions &LangOpts)
Definition: FixitUtil.cpp:217
std::optional< std::string > getPointeeTypeText(const DeclaratorDecl *VD, const SourceManager &SM, const LangOptions &LangOpts, std::optional< Qualifiers > *QualifiersToAppend)
Definition: FixitUtil.cpp:22
std::optional< StringRef > getRangeText(SourceRange SR, const SourceManager &SM, const LangOptions &LangOpts)
Definition: FixitUtil.cpp:185
std::optional< StringRef > getVarDeclIdentifierText(const DeclaratorDecl *VD, const SourceManager &SM, const LangOptions &LangOpts)
Definition: FixitUtil.cpp:199
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