clang  10.0.0svn
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);
59  const SourceLocation Begin = FullExpr->getSourceRange().getBegin();
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;
109  CharSourceRange::getTokenRange(Begin, Begin)));
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,
136  S, Begin, VK_RValue);
137  if (CanConvert) {
138 
139  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
140  if (UO->getOpcode() == UO_Deref) {
141  FixKind = OFIK_RemoveDereference;
143  CharSourceRange::getTokenRange(Begin, Begin)));
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 
199 std::string
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 
218 std::string
220  return getScalarZeroExpressionForType(*T, Loc, *this);
221 }
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.
Defines the clang::ASTContext interface.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2585
A (possibly-)qualified type.
Definition: Type.h:643
bool isBlockPointerType() const
Definition: Type.h:6399
bool isMemberPointerType() const
Definition: Type.h:6429
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2024
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 CharSourceRange getTokenRange(SourceRange R)
The base class of the type hierarchy.
Definition: Type.h:1436
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
Definition: Sema.cpp:49
bool isEnumeralType() const
Definition: Type.h:6475
bool isChar32Type() const
Definition: Type.cpp:1902
bool hasDefinition() const
Definition: DeclCXX.h:542
std::vector< FixItHint > Hints
The list of Hints generated so far.
Defines the clang::Expr interface and subclasses for C++ expressions.
bool isWideCharType() const
Definition: Type.cpp:1883
FullExpr - Represents a "full-expression" node.
Definition: Expr.h:925
bool isCharType() const
Definition: Type.cpp:1874
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
IdentifierTable & Idents
Definition: ASTContext.h:579
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:125
static std::string getScalarZeroExpressionForType(const Type &T, SourceLocation Loc, const Sema &S)
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:2971
Preprocessor & PP
Definition: Sema.h:376
bool isScalarType() const
Definition: Type.h:6739
An ordinary object is located at an address in memory.
Definition: Specifiers.h:141
const LangOptions & LangOpts
Definition: Sema.h:375
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:2950
std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const
bool hasUserProvidedDefaultConstructor() const
Whether this class has a user-provided default constructor per C++11.
Definition: DeclCXX.h:755
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:331
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1692
This represents one expression.
Definition: Expr.h:108
SourceLocation End
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:122
bool isChar16Type() const
Definition: Type.cpp:1896
Defines the clang::Preprocessor interface.
SourceLocation Begin
OverloadFixItKind
bool isAtLeastAsQualifiedAs(CanQual< T > Other) const
Determines whether this canonical type is at least as qualified as the Other canonical type...
SourceLocation getEnd() const
UnaryOperator - This represents the unary-expression&#39;s (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
Definition: Expr.h:2021
TypeComparisonFuncTy CompareTypes
The type comparison function used to decide if expression FromExpr of type FromTy can be converted to...
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:421
Kind
ASTContext & getASTContext() const
Definition: Sema.h:1295
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Specifies that a value-dependent expression should be considered to never be a null pointer constant...
Definition: Expr.h:737
bool isObjCObjectPointerType() const
Definition: Type.h:6495
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
Definition: Expr.h:258
std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const
Get a string to suggest for zero-initialization of a type.
Dataflow Directional Tag Classes.
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition: Diagnostic.h:118
bool isBooleanType() const
Definition: Type.h:6767
CanQual< Type > getNonReferenceType() const
If the canonical type is a reference type, returns the type that it refers to; otherwise, returns the type itself.
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:92
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2289
Represents a C++ struct/union/class.
Definition: DeclCXX.h:255
static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name)
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:262
bool isPointerType() const
Definition: Type.h:6391
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:129
ASTContext & Context
Definition: Sema.h:377
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:1057
SourceLocation getBegin() const
unsigned NumConversionsFixed
The number of Conversions fixed.