clang  14.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,
25  SourceLocation Loc,
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 (isa<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  CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy, S,
136  Begin, VK_PRValue);
137  if (CanConvert) {
138 
139  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
140  if (UO->getOpcode() == UO_Deref) {
141  FixKind = OFIK_RemoveDereference;
144  }
145  } else if (NeedParen) {
146  Hints.push_back(FixItHint::CreateInsertion(Begin, "&("));
147  Hints.push_back(FixItHint::CreateInsertion(End, ")"));
148  } else {
149  Hints.push_back(FixItHint::CreateInsertion(Begin, "&"));
150  }
151 
153  if (NumConversionsFixed == 1)
154  Kind = FixKind;
155  return true;
156  }
157  }
158 
159  return false;
160 }
161 
162 static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name) {
163  return (bool)S.PP.getMacroDefinitionAtLoc(&S.getASTContext().Idents.get(Name),
164  Loc);
165 }
166 
168  const Type &T, SourceLocation Loc, const Sema &S) {
169  assert(T.isScalarType() && "use scalar types only");
170  // Suggest "0" for non-enumeration scalar types, unless we can find a
171  // better initializer.
172  if (T.isEnumeralType())
173  return std::string();
174  if ((T.isObjCObjectPointerType() || T.isBlockPointerType()) &&
175  isMacroDefined(S, Loc, "nil"))
176  return "nil";
177  if (T.isRealFloatingType())
178  return "0.0";
179  if (T.isBooleanType() &&
180  (S.LangOpts.CPlusPlus || isMacroDefined(S, Loc, "false")))
181  return "false";
182  if (T.isPointerType() || T.isMemberPointerType()) {
183  if (S.LangOpts.CPlusPlus11)
184  return "nullptr";
185  if (isMacroDefined(S, Loc, "NULL"))
186  return "NULL";
187  }
188  if (T.isCharType())
189  return "'\\0'";
190  if (T.isWideCharType())
191  return "L'\\0'";
192  if (T.isChar16Type())
193  return "u'\\0'";
194  if (T.isChar32Type())
195  return "U'\\0'";
196  return "0";
197 }
198 
201  if (T->isScalarType()) {
202  std::string s = getScalarZeroExpressionForType(*T, Loc, *this);
203  if (!s.empty())
204  s = " = " + s;
205  return s;
206  }
207 
208  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
209  if (!RD || !RD->hasDefinition())
210  return std::string();
211  if (LangOpts.CPlusPlus11 && !RD->hasUserProvidedDefaultConstructor())
212  return "{}";
213  if (RD->isAggregate())
214  return " = {}";
215  return std::string();
216 }
217 
220  return getScalarZeroExpressionForType(*T, Loc, *this);
221 }
clang::Type::isBlockPointerType
bool isBlockPointerType() const
Definition: Type.h:6680
clang::OK_Ordinary
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:136
clang::Expr::isLValue
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:270
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::Sema::getFixItZeroLiteralForType
std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const
Definition: SemaFixItUtils.cpp:219
clang::FixItHint::CreateInsertion
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:96
clang::Sema::getASTContext
ASTContext & getASTContext() const
Definition: Sema.h:1576
clang::Type::isCharType
bool isCharType() const
Definition: Type.cpp:1956
clang::IdentifierTable::get
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Definition: IdentifierTable.h:592
clang::Sema::getFixItZeroInitializerForType
std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const
Get a string to suggest for zero-initialization of a type.
Definition: SemaFixItUtils.cpp:200
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
clang::SourceRange::getBegin
SourceLocation getBegin() const
Definition: SourceLocation.h:221
clang::Type::isWideCharType
bool isWideCharType() const
Definition: Type.cpp:1965
clang::Stmt::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:324
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:673
clang::Expr::getObjectKind
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:437
clang::Type::isScalarType
bool isScalarType() const
Definition: Type.h:7042
clang::Type::isRealFloatingType
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2120
clang::UnaryOperator
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2157
clang::Expr::IgnoreImpCasts
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:2899
End
SourceLocation End
Definition: USRLocFinder.cpp:167
clang::Sema::Context
ASTContext & Context
Definition: Sema.h:411
clang::Type
The base class of the type hierarchy.
Definition: Type.h:1490
Preprocessor.h
clang::FullExpr
FullExpr - Represents a "full-expression" node.
Definition: Expr.h:998
clang::Preprocessor::getMacroDefinitionAtLoc
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
Definition: Preprocessor.h:1125
clang::ConversionFixItGenerator::tryToFixConversion
bool tryToFixConversion(const Expr *FromExpr, const QualType FromQTy, const QualType ToQTy, Sema &S)
If possible, generates and stores a fix for the given conversion.
Definition: SemaFixItUtils.cpp:50
clang::ConversionFixItGenerator::Hints
std::vector< FixItHint > Hints
The list of Hints generated so far.
Definition: SemaFixItUtils.h:41
clang::SourceRange::getEnd
SourceLocation getEnd() const
Definition: SourceLocation.h:222
clang::CXXRecordDecl::isAggregate
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:1098
clang::Expr::NPC_ValueDependentIsNotNull
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Definition: Expr.h:784
clang::ConversionFixItGenerator::NumConversionsFixed
unsigned NumConversionsFixed
The number of Conversions fixed.
Definition: SemaFixItUtils.h:45
ASTContext.h
clang::ConversionFixItGenerator::compareTypesSimple
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.
Definition: SemaFixItUtils.cpp:22
clang::ASTContext::getCanonicalType
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2468
clang::Type::getAsCXXRecordDecl
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1760
clang::Sema::getLocForEndOfToken
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
Definition: Sema.cpp:54
ExprObjC.h
clang::CanQual< Type >
ExprCXX.h
clang::Type::isEnumeralType
bool isEnumeralType() const
Definition: Type.h:6766
Sema.h
clang::Sema::LangOpts
const LangOptions & LangOpts
Definition: Sema.h:409
clang::Type::isObjCObjectPointerType
bool isObjCObjectPointerType() const
Definition: Type.h:6794
getScalarZeroExpressionForType
static std::string getScalarZeroExpressionForType(const Type &T, SourceLocation Loc, const Sema &S)
Definition: SemaFixItUtils.cpp:167
clang::VK_LValue
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:124
clang::Expr::IgnoreParenCasts
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:2924
clang::CXXRecordDecl
Represents a C++ struct/union/class.
Definition: DeclCXX.h:255
clang::VK_PRValue
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:120
clang::Sema::IsDerivedFrom
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
Definition: SemaDeclCXX.cpp:2808
clang::Type::isMemberPointerType
bool isMemberPointerType() const
Definition: Type.h:6720
clang::Type::isPointerType
bool isPointerType() const
Definition: Type.h:6672
clang::ASTContext::Idents
IdentifierTable & Idents
Definition: ASTContext.h:648
clang::CharSourceRange::getTokenRange
static CharSourceRange getTokenRange(SourceRange R)
Definition: SourceLocation.h:263
Begin
SourceLocation Begin
Definition: USRLocFinder.cpp:165
clang::ConversionFixItGenerator::Kind
OverloadFixItKind Kind
The type of fix applied.
Definition: SemaFixItUtils.h:49
clang::Sema
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:355
clang::CanQual::getNonReferenceType
CanQual< Type > getNonReferenceType() const
If the canonical type is a reference type, returns the type that it refers to; otherwise,...
Definition: CanonicalType.h:625
clang::ExprValueKind
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:117
clang::OFIK_TakeAddress
@ OFIK_TakeAddress
Definition: SemaFixItUtils.h:22
clang::Type::isBooleanType
bool isBooleanType() const
Definition: Type.h:7071
clang::PointerType
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2640
clang::CanQual::getUnqualifiedType
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
Definition: CanonicalType.h:620
clang
Definition: CalledOnceCheck.h:17
SemaFixItUtils.h
clang::ConversionFixItGenerator::CompareTypes
TypeComparisonFuncTy CompareTypes
The type comparison function used to decide if expression FromExpr of type FromTy can be converted to...
Definition: SemaFixItUtils.h:59
clang::CXXRecordDecl::hasDefinition
bool hasDefinition() const
Definition: DeclCXX.h:542
clang::FixItHint::CreateRemoval
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition: Diagnostic.h:122
s
__device__ __2f16 float bool s
Definition: __clang_hip_libdevice_declares.h:315
clang::CXXRecordDecl::hasUserProvidedDefaultConstructor
bool hasUserProvidedDefaultConstructor() const
Whether this class has a user-provided default constructor per C++11.
Definition: DeclCXX.h:767
clang::ASTContext::getPointerType
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
Definition: ASTContext.cpp:3249
clang::OFIK_RemoveDereference
@ OFIK_RemoveDereference
Definition: SemaFixItUtils.h:23
clang::CanQual::isAtLeastAsQualifiedAs
bool isAtLeastAsQualifiedAs(CanQual< T > Other) const
Determines whether this canonical type is at least as qualified as the Other canonical type.
Definition: CanonicalType.h:173
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::OFIK_RemoveTakeAddress
@ OFIK_RemoveTakeAddress
Definition: SemaFixItUtils.h:24
clang::Sema::PP
Preprocessor & PP
Definition: Sema.h:410
clang::Type::isChar16Type
bool isChar16Type() const
Definition: Type.cpp:1978
clang::OFIK_Dereference
@ OFIK_Dereference
Definition: SemaFixItUtils.h:21
clang::Type::isChar32Type
bool isChar32Type() const
Definition: Type.cpp:1984
clang::OverloadFixItKind
OverloadFixItKind
Definition: SemaFixItUtils.h:19
isMacroDefined
static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name)
Definition: SemaFixItUtils.cpp:162