clang  6.0.0svn
SemaFixItUtils.cpp
Go to the documentation of this file.
1 //===--- SemaFixItUtils.cpp - Sema FixIts ---------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines helper classes for generation of Sema FixItHints.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/ExprCXX.h"
16 #include "clang/AST/ExprObjC.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Sema/Sema.h"
20 
21 using namespace clang;
22 
24  CanQualType To,
25  Sema &S,
26  SourceLocation Loc,
27  ExprValueKind FromVK) {
28  if (!To.isAtLeastAsQualifiedAs(From))
29  return false;
30 
31  From = From.getNonReferenceType();
32  To = To.getNonReferenceType();
33 
34  // If both are pointer types, work with the pointee types.
35  if (isa<PointerType>(From) && isa<PointerType>(To)) {
36  From = S.Context.getCanonicalType(
37  (cast<PointerType>(From))->getPointeeType());
39  (cast<PointerType>(To))->getPointeeType());
40  }
41 
42  const CanQualType FromUnq = From.getUnqualifiedType();
43  const CanQualType ToUnq = To.getUnqualifiedType();
44 
45  if ((FromUnq == ToUnq || (S.IsDerivedFrom(Loc, FromUnq, ToUnq)) ) &&
46  To.isAtLeastAsQualifiedAs(From))
47  return true;
48  return false;
49 }
50 
52  const QualType FromTy,
53  const QualType ToTy,
54  Sema &S) {
55  if (!FullExpr)
56  return false;
57 
58  const CanQualType FromQTy = S.Context.getCanonicalType(FromTy);
59  const CanQualType ToQTy = S.Context.getCanonicalType(ToTy);
60  const SourceLocation Begin = FullExpr->getSourceRange().getBegin();
62  .getEnd());
63 
64  // Strip the implicit casts - those are implied by the compiler, not the
65  // original source code.
66  const Expr* Expr = FullExpr->IgnoreImpCasts();
67 
68  bool NeedParen = true;
69  if (isa<ArraySubscriptExpr>(Expr) ||
70  isa<CallExpr>(Expr) ||
71  isa<DeclRefExpr>(Expr) ||
72  isa<CastExpr>(Expr) ||
73  isa<CXXNewExpr>(Expr) ||
74  isa<CXXConstructExpr>(Expr) ||
75  isa<CXXDeleteExpr>(Expr) ||
76  isa<CXXNoexceptExpr>(Expr) ||
77  isa<CXXPseudoDestructorExpr>(Expr) ||
78  isa<CXXScalarValueInitExpr>(Expr) ||
79  isa<CXXThisExpr>(Expr) ||
80  isa<CXXTypeidExpr>(Expr) ||
81  isa<CXXUnresolvedConstructExpr>(Expr) ||
82  isa<ObjCMessageExpr>(Expr) ||
83  isa<ObjCPropertyRefExpr>(Expr) ||
84  isa<ObjCProtocolExpr>(Expr) ||
85  isa<MemberExpr>(Expr) ||
86  isa<ParenExpr>(FullExpr) ||
87  isa<ParenListExpr>(Expr) ||
88  isa<SizeOfPackExpr>(Expr) ||
89  isa<UnaryOperator>(Expr))
90  NeedParen = false;
91 
92  // Check if the argument needs to be dereferenced:
93  // (type * -> type) or (type * -> type &).
94  if (const PointerType *FromPtrTy = dyn_cast<PointerType>(FromQTy)) {
96 
97  bool CanConvert = CompareTypes(
98  S.Context.getCanonicalType(FromPtrTy->getPointeeType()), ToQTy,
99  S, Begin, VK_LValue);
100  if (CanConvert) {
101  // Do not suggest dereferencing a Null pointer.
102  if (Expr->IgnoreParenCasts()->
103  isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull))
104  return false;
105 
106  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
107  if (UO->getOpcode() == UO_AddrOf) {
108  FixKind = OFIK_RemoveTakeAddress;
110  CharSourceRange::getTokenRange(Begin, Begin)));
111  }
112  } else if (NeedParen) {
113  Hints.push_back(FixItHint::CreateInsertion(Begin, "*("));
114  Hints.push_back(FixItHint::CreateInsertion(End, ")"));
115  } else {
116  Hints.push_back(FixItHint::CreateInsertion(Begin, "*"));
117  }
118 
120  if (NumConversionsFixed == 1)
121  Kind = FixKind;
122  return true;
123  }
124  }
125 
126  // Check if the pointer to the argument needs to be passed:
127  // (type -> type *) or (type & -> type *).
128  if (isa<PointerType>(ToQTy)) {
129  bool CanConvert = false;
131 
132  // Only suggest taking address of L-values.
133  if (!Expr->isLValue() || Expr->getObjectKind() != OK_Ordinary)
134  return false;
135 
136  CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy,
137  S, Begin, VK_RValue);
138  if (CanConvert) {
139 
140  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
141  if (UO->getOpcode() == UO_Deref) {
142  FixKind = OFIK_RemoveDereference;
144  CharSourceRange::getTokenRange(Begin, Begin)));
145  }
146  } else if (NeedParen) {
147  Hints.push_back(FixItHint::CreateInsertion(Begin, "&("));
148  Hints.push_back(FixItHint::CreateInsertion(End, ")"));
149  } else {
150  Hints.push_back(FixItHint::CreateInsertion(Begin, "&"));
151  }
152 
154  if (NumConversionsFixed == 1)
155  Kind = FixKind;
156  return true;
157  }
158  }
159 
160  return false;
161 }
162 
163 static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name) {
164  return (bool)S.PP.getMacroDefinitionAtLoc(&S.getASTContext().Idents.get(Name),
165  Loc);
166 }
167 
169  const Type &T, SourceLocation Loc, const Sema &S) {
170  assert(T.isScalarType() && "use scalar types only");
171  // Suggest "0" for non-enumeration scalar types, unless we can find a
172  // better initializer.
173  if (T.isEnumeralType())
174  return std::string();
175  if ((T.isObjCObjectPointerType() || T.isBlockPointerType()) &&
176  isMacroDefined(S, Loc, "nil"))
177  return "nil";
178  if (T.isRealFloatingType())
179  return "0.0";
180  if (T.isBooleanType() &&
181  (S.LangOpts.CPlusPlus || isMacroDefined(S, Loc, "false")))
182  return "false";
183  if (T.isPointerType() || T.isMemberPointerType()) {
184  if (S.LangOpts.CPlusPlus11)
185  return "nullptr";
186  if (isMacroDefined(S, Loc, "NULL"))
187  return "NULL";
188  }
189  if (T.isCharType())
190  return "'\\0'";
191  if (T.isWideCharType())
192  return "L'\\0'";
193  if (T.isChar16Type())
194  return "u'\\0'";
195  if (T.isChar32Type())
196  return "U'\\0'";
197  return "0";
198 }
199 
200 std::string
202  if (T->isScalarType()) {
203  std::string s = getScalarZeroExpressionForType(*T, Loc, *this);
204  if (!s.empty())
205  s = " = " + s;
206  return s;
207  }
208 
209  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
210  if (!RD || !RD->hasDefinition())
211  return std::string();
212  if (LangOpts.CPlusPlus11 && !RD->hasUserProvidedDefaultConstructor())
213  return "{}";
214  if (RD->isAggregate())
215  return " = {}";
216  return std::string();
217 }
218 
219 std::string
221  return getScalarZeroExpressionForType(*T, Loc, *this);
222 }
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:2285
A (possibly-)qualified type.
Definition: Type.h:653
bool isBlockPointerType() const
Definition: Type.h:5952
bool isMemberPointerType() const
Definition: Type.h:5975
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:1893
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:1353
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
Definition: Sema.cpp:45
bool isEnumeralType() const
Definition: Type.h:6021
bool isChar32Type() const
Definition: Type.cpp:1772
bool hasDefinition() const
Definition: DeclCXX.h:738
std::vector< FixItHint > Hints
The list of Hints generated so far.
Defines the clang::Expr interface and subclasses for C++ expressions.
Expr * IgnoreImpCasts() LLVM_READONLY
IgnoreImpCasts - Skip past any implicit casts which might surround this expression.
Definition: Expr.h:2865
bool isWideCharType() const
Definition: Type.cpp:1759
bool isCharType() const
Definition: Type.cpp:1750
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:537
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:107
static std::string getScalarZeroExpressionForType(const Type &T, SourceLocation Loc, const Sema &S)
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2463
Preprocessor & PP
Definition: Sema.h:315
bool isScalarType() const
Definition: Type.h:6206
An ordinary object is located at an address in memory.
Definition: Specifiers.h:123
const LangOptions & LangOpts
Definition: Sema.h:314
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:942
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:274
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1590
Expr - This represents one expression.
Definition: Expr.h:106
SourceLocation End
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:104
const FunctionProtoType * T
bool isChar16Type() const
Definition: Type.cpp:1766
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:1717
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:412
Kind
ASTContext & getASTContext() const
Definition: Sema.h:1200
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:706
bool isObjCObjectPointerType() const
Definition: Type.h:6041
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
Definition: Preprocessor.h:953
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
Definition: Expr.h:249
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:116
bool isBooleanType() const
Definition: Type.h:6234
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:90
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2174
Represents a C++ struct/union/class.
Definition: DeclCXX.h:299
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:265
bool isPointerType() const
Definition: Type.h:5944
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:111
ASTContext & Context
Definition: Sema.h:316
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:1236
SourceLocation getBegin() const
unsigned NumConversionsFixed
The number of Conversions fixed.