clang  20.0.0git
SemaFixItUtils.cpp
Go to the documentation of this file.
1 //===--- SemaFixItUtils.cpp - Sema FixIts ---------------------------------===//
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 classes for generation of Sema FixItHints.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/ExprCXX.h"
15 #include "clang/AST/ExprObjC.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "clang/Sema/Sema.h"
19 
20 using namespace clang;
21 
23  CanQualType To,
24  Sema &S,
26  ExprValueKind FromVK) {
27  if (!To.isAtLeastAsQualifiedAs(From))
28  return false;
29 
30  From = From.getNonReferenceType();
31  To = To.getNonReferenceType();
32 
33  // If both are pointer types, work with the pointee types.
34  if (isa<PointerType>(From) && isa<PointerType>(To)) {
35  From = S.Context.getCanonicalType(
36  (cast<PointerType>(From))->getPointeeType());
38  (cast<PointerType>(To))->getPointeeType());
39  }
40 
41  const CanQualType FromUnq = From.getUnqualifiedType();
42  const CanQualType ToUnq = To.getUnqualifiedType();
43 
44  if ((FromUnq == ToUnq || (S.IsDerivedFrom(Loc, FromUnq, ToUnq)) ) &&
45  To.isAtLeastAsQualifiedAs(From))
46  return true;
47  return false;
48 }
49 
51  const QualType FromTy,
52  const QualType ToTy,
53  Sema &S) {
54  if (!FullExpr)
55  return false;
56 
57  const CanQualType FromQTy = S.Context.getCanonicalType(FromTy);
58  const CanQualType ToQTy = S.Context.getCanonicalType(ToTy);
61  .getEnd());
62 
63  // Strip the implicit casts - those are implied by the compiler, not the
64  // original source code.
65  const Expr* Expr = FullExpr->IgnoreImpCasts();
66 
67  bool NeedParen = true;
68  if (isa<ArraySubscriptExpr>(Expr) ||
69  isa<CallExpr>(Expr) ||
70  isa<DeclRefExpr>(Expr) ||
71  isa<CastExpr>(Expr) ||
72  isa<CXXNewExpr>(Expr) ||
73  isa<CXXConstructExpr>(Expr) ||
74  isa<CXXDeleteExpr>(Expr) ||
75  isa<CXXNoexceptExpr>(Expr) ||
76  isa<CXXPseudoDestructorExpr>(Expr) ||
77  isa<CXXScalarValueInitExpr>(Expr) ||
78  isa<CXXThisExpr>(Expr) ||
79  isa<CXXTypeidExpr>(Expr) ||
80  isa<CXXUnresolvedConstructExpr>(Expr) ||
81  isa<ObjCMessageExpr>(Expr) ||
82  isa<ObjCPropertyRefExpr>(Expr) ||
83  isa<ObjCProtocolExpr>(Expr) ||
84  isa<MemberExpr>(Expr) ||
85  isa<ParenExpr>(FullExpr) ||
86  isa<ParenListExpr>(Expr) ||
87  isa<SizeOfPackExpr>(Expr) ||
88  isa<UnaryOperator>(Expr))
89  NeedParen = false;
90 
91  // Check if the argument needs to be dereferenced:
92  // (type * -> type) or (type * -> type &).
93  if (const PointerType *FromPtrTy = dyn_cast<PointerType>(FromQTy)) {
95 
96  bool CanConvert = CompareTypes(
97  S.Context.getCanonicalType(FromPtrTy->getPointeeType()), ToQTy,
98  S, Begin, VK_LValue);
99  if (CanConvert) {
100  // Do not suggest dereferencing a Null pointer.
101  if (Expr->IgnoreParenCasts()->
102  isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull))
103  return false;
104 
105  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
106  if (UO->getOpcode() == UO_AddrOf) {
107  FixKind = OFIK_RemoveTakeAddress;
110  }
111  } else if (NeedParen) {
112  Hints.push_back(FixItHint::CreateInsertion(Begin, "*("));
113  Hints.push_back(FixItHint::CreateInsertion(End, ")"));
114  } else {
115  Hints.push_back(FixItHint::CreateInsertion(Begin, "*"));
116  }
117 
119  if (NumConversionsFixed == 1)
120  Kind = FixKind;
121  return true;
122  }
123  }
124 
125  // Check if the pointer to the argument needs to be passed:
126  // (type -> type *) or (type & -> type *).
127  if (const auto *ToPtrTy = dyn_cast<PointerType>(ToQTy)) {
128  bool CanConvert = false;
130 
131  // Only suggest taking address of L-values.
132  if (!Expr->isLValue() || Expr->getObjectKind() != OK_Ordinary)
133  return false;
134 
135  // Do no take address of const pointer to get void*
136  if (isa<PointerType>(FromQTy) && ToPtrTy->isVoidPointerType())
137  return false;
138 
139  CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy, S,
140  Begin, VK_PRValue);
141  if (CanConvert) {
142 
143  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
144  if (UO->getOpcode() == UO_Deref) {
145  FixKind = OFIK_RemoveDereference;
148  }
149  } else if (NeedParen) {
150  Hints.push_back(FixItHint::CreateInsertion(Begin, "&("));
151  Hints.push_back(FixItHint::CreateInsertion(End, ")"));
152  } else {
153  Hints.push_back(FixItHint::CreateInsertion(Begin, "&"));
154  }
155 
157  if (NumConversionsFixed == 1)
158  Kind = FixKind;
159  return true;
160  }
161  }
162 
163  return false;
164 }
165 
166 static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name) {
167  return (bool)S.PP.getMacroDefinitionAtLoc(&S.getASTContext().Idents.get(Name),
168  Loc);
169 }
170 
172  const Type &T, SourceLocation Loc, const Sema &S) {
173  assert(T.isScalarType() && "use scalar types only");
174  // Suggest "0" for non-enumeration scalar types, unless we can find a
175  // better initializer.
176  if (T.isEnumeralType())
177  return std::string();
179  isMacroDefined(S, Loc, "nil"))
180  return "nil";
181  if (T.isRealFloatingType())
182  return "0.0";
183  if (T.isBooleanType() &&
184  (S.LangOpts.CPlusPlus || isMacroDefined(S, Loc, "false")))
185  return "false";
186  if (T.isPointerType() || T.isMemberPointerType()) {
187  if (S.LangOpts.CPlusPlus11)
188  return "nullptr";
189  if (isMacroDefined(S, Loc, "NULL"))
190  return "NULL";
191  }
192  if (T.isCharType())
193  return "'\\0'";
194  if (T.isWideCharType())
195  return "L'\\0'";
196  if (T.isChar16Type())
197  return "u'\\0'";
198  if (T.isChar32Type())
199  return "U'\\0'";
200  return "0";
201 }
202 
203 std::string
205  if (T->isScalarType()) {
206  std::string s = getScalarZeroExpressionForType(*T, Loc, *this);
207  if (!s.empty())
208  s = " = " + s;
209  return s;
210  }
211 
212  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
213  if (!RD || !RD->hasDefinition())
214  return std::string();
215  if (LangOpts.CPlusPlus11 && !RD->hasUserProvidedDefaultConstructor())
216  return "{}";
217  if (RD->isAggregate())
218  return " = {}";
219  return std::string();
220 }
221 
222 std::string
224  return getScalarZeroExpressionForType(*T, Loc, *this);
225 }
Defines the clang::ASTContext interface.
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines the clang::Preprocessor interface.
static std::string getScalarZeroExpressionForType(const Type &T, SourceLocation Loc, const Sema &S)
static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name)
SourceLocation Loc
Definition: SemaObjC.cpp:759
static QualType getPointeeType(const MemRegion *R)
SourceLocation End
SourceLocation Begin
__device__ __2f16 float __ockl_bool s
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2633
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
IdentifierTable & Idents
Definition: ASTContext.h:660
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool isAggregate() const
Determine whether this class is an aggregate (C++ [dcl.init.aggr]), which is a class with no user-dec...
Definition: DeclCXX.h:1148
bool hasUserProvidedDefaultConstructor() const
Whether this class has a user-provided default constructor per C++11.
Definition: DeclCXX.h:798
bool hasDefinition() const
Definition: DeclCXX.h:572
CanQual< Type > getNonReferenceType() const
If the canonical type is a reference type, returns the type that it refers to; otherwise,...
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
bool isAtLeastAsQualifiedAs(CanQual< T > Other) const
Determines whether this canonical type is at least as qualified as the Other canonical type.
static CharSourceRange getTokenRange(SourceRange R)
This represents one expression.
Definition: Expr.h:110
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3127
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:277
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Definition: Expr.h:830
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:444
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3102
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition: Diagnostic.h:124
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition: Diagnostic.h:98
FullExpr - Represents a "full-expression" node.
Definition: Expr.h:1044
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3197
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
A (possibly-)qualified type.
Definition: Type.h:941
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:493
ASTContext & Context
Definition: Sema.h:962
std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const
std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const
Get a string to suggest for zero-initialization of a type.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
Definition: Sema.cpp:84
Preprocessor & PP
Definition: Sema.h:961
const LangOptions & LangOpts
Definition: Sema.h:960
ASTContext & getASTContext() const
Definition: Sema.h:560
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
Encodes a location in the source.
SourceLocation getEnd() const
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
The base class of the type hierarchy.
Definition: Type.h:1829
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1882
bool isBlockPointerType() const
Definition: Type.h:8027
bool isBooleanType() const
Definition: Type.h:8475
bool isCharType() const
Definition: Type.cpp:2089
bool isPointerType() const
Definition: Type.h:8013
bool isEnumeralType() const
Definition: Type.h:8117
bool isScalarType() const
Definition: Type.h:8446
bool isChar16Type() const
Definition: Type.cpp:2111
bool isMemberPointerType() const
Definition: Type.h:8067
bool isChar32Type() const
Definition: Type.cpp:2117
bool isObjCObjectPointerType() const
Definition: Type.h:8155
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2266
bool isWideCharType() const
Definition: Type.cpp:2098
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2240
The JSON file list parser is used to communicate input to InstallAPI.
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
OverloadFixItKind
@ OFIK_Dereference
@ OFIK_TakeAddress
@ OFIK_RemoveDereference
@ OFIK_RemoveTakeAddress
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:132
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
const FunctionProtoType * T
OverloadFixItKind Kind
The type of fix applied.
unsigned NumConversionsFixed
The number of Conversions fixed.
TypeComparisonFuncTy CompareTypes
The type comparison function used to decide if expression FromExpr of type FromTy can be converted to...
bool tryToFixConversion(const Expr *FromExpr, const QualType FromQTy, const QualType ToQTy, Sema &S)
If possible, generates and stores a fix for the given conversion.
static bool compareTypesSimple(CanQualType From, CanQualType To, Sema &S, SourceLocation Loc, ExprValueKind FromVK)
Performs a simple check to see if From type can be converted to To type.
std::vector< FixItHint > Hints
The list of Hints generated so far.