clang  6.0.0svn
TransUnbridgedCasts.cpp
Go to the documentation of this file.
1 //===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===//
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 // rewriteUnbridgedCasts:
11 //
12 // A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
13 // is from a file-level variable, __bridge cast is used to convert it.
14 // For the result of a function call that we know is +1/+0,
15 // __bridge/CFBridgingRelease is used.
16 //
17 // NSString *str = (NSString *)kUTTypePlainText;
18 // str = b ? kUTTypeRTF : kUTTypePlainText;
19 // NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault,
20 // _uuid);
21 // ---->
22 // NSString *str = (__bridge NSString *)kUTTypePlainText;
23 // str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
24 // NSString *_uuidString = (NSString *)
25 // CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));
26 //
27 // For a C pointer to ObjC, for casting 'self', __bridge is used.
28 //
29 // CFStringRef str = (CFStringRef)self;
30 // ---->
31 // CFStringRef str = (__bridge CFStringRef)self;
32 //
33 // Uses of Block_copy/Block_release macros are rewritten:
34 //
35 // c = Block_copy(b);
36 // Block_release(c);
37 // ---->
38 // c = [b copy];
39 // <removed>
40 //
41 //===----------------------------------------------------------------------===//
42 
43 #include "Transforms.h"
44 #include "Internals.h"
45 #include "clang/AST/ASTContext.h"
46 #include "clang/AST/Attr.h"
47 #include "clang/AST/ParentMap.h"
50 #include "clang/Lex/Lexer.h"
52 #include "llvm/ADT/SmallString.h"
53 
54 using namespace clang;
55 using namespace arcmt;
56 using namespace trans;
57 
58 namespace {
59 
60 class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
61  MigrationPass &Pass;
62  IdentifierInfo *SelfII;
63  std::unique_ptr<ParentMap> StmtMap;
64  Decl *ParentD;
65  Stmt *Body;
66  mutable std::unique_ptr<ExprSet> Removables;
67 
68 public:
69  UnbridgedCastRewriter(MigrationPass &pass)
70  : Pass(pass), ParentD(nullptr), Body(nullptr) {
71  SelfII = &Pass.Ctx.Idents.get("self");
72  }
73 
74  void transformBody(Stmt *body, Decl *ParentD) {
75  this->ParentD = ParentD;
76  Body = body;
77  StmtMap.reset(new ParentMap(body));
78  TraverseStmt(body);
79  }
80 
81  bool TraverseBlockDecl(BlockDecl *D) {
82  // ParentMap does not enter into a BlockDecl to record its stmts, so use a
83  // new UnbridgedCastRewriter to handle the block.
84  UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D);
85  return true;
86  }
87 
88  bool VisitCastExpr(CastExpr *E) {
89  if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
90  E->getCastKind() != CK_BitCast &&
91  E->getCastKind() != CK_AnyPointerToBlockPointerCast)
92  return true;
93 
94  QualType castType = E->getType();
95  Expr *castExpr = E->getSubExpr();
96  QualType castExprType = castExpr->getType();
97 
98  if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
99  return true;
100 
101  bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
102  bool castRetainable = castType->isObjCIndirectLifetimeType();
103  if (exprRetainable == castRetainable) return true;
104 
105  if (castExpr->isNullPointerConstant(Pass.Ctx,
107  return true;
108 
109  SourceLocation loc = castExpr->getExprLoc();
110  if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
111  return true;
112 
113  if (castType->isObjCRetainableType())
114  transformNonObjCToObjCCast(E);
115  else
116  transformObjCToNonObjCCast(E);
117 
118  return true;
119  }
120 
121 private:
122  void transformNonObjCToObjCCast(CastExpr *E) {
123  if (!E) return;
124 
125  // Global vars are assumed that are cast as unretained.
126  if (isGlobalVar(E))
127  if (E->getSubExpr()->getType()->isPointerType()) {
128  castToObjCObject(E, /*retained=*/false);
129  return;
130  }
131 
132  // If the cast is directly over the result of a Core Foundation function
133  // try to figure out whether it should be cast as retained or unretained.
134  Expr *inner = E->IgnoreParenCasts();
135  if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
136  if (FunctionDecl *FD = callE->getDirectCallee()) {
137  if (FD->hasAttr<CFReturnsRetainedAttr>()) {
138  castToObjCObject(E, /*retained=*/true);
139  return;
140  }
141  if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
142  castToObjCObject(E, /*retained=*/false);
143  return;
144  }
145  if (FD->isGlobal() &&
146  FD->getIdentifier() &&
148  FD->getIdentifier()->getName())) {
149  StringRef fname = FD->getIdentifier()->getName();
150  if (fname.endswith("Retain") ||
151  fname.find("Create") != StringRef::npos ||
152  fname.find("Copy") != StringRef::npos) {
153  // Do not migrate to couple of bridge transfer casts which
154  // cancel each other out. Leave it unchanged so error gets user
155  // attention instead.
156  if (FD->getName() == "CFRetain" &&
157  FD->getNumParams() == 1 &&
158  FD->getParent()->isTranslationUnit() &&
159  FD->isExternallyVisible()) {
160  Expr *Arg = callE->getArg(0);
161  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
162  const Expr *sub = ICE->getSubExpr();
163  QualType T = sub->getType();
164  if (T->isObjCObjectPointerType())
165  return;
166  }
167  }
168  castToObjCObject(E, /*retained=*/true);
169  return;
170  }
171 
172  if (fname.find("Get") != StringRef::npos) {
173  castToObjCObject(E, /*retained=*/false);
174  return;
175  }
176  }
177  }
178  }
179 
180  // If returning an ivar or a member of an ivar from a +0 method, use
181  // a __bridge cast.
182  Expr *base = inner->IgnoreParenImpCasts();
183  while (isa<MemberExpr>(base))
184  base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts();
185  if (isa<ObjCIvarRefExpr>(base) &&
186  isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
187  if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
188  if (!method->hasAttr<NSReturnsRetainedAttr>()) {
189  castToObjCObject(E, /*retained=*/false);
190  return;
191  }
192  }
193  }
194  }
195 
196  void castToObjCObject(CastExpr *E, bool retained) {
197  rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
198  }
199 
200  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
201  Transaction Trans(Pass.TA);
202  rewriteToBridgedCast(E, Kind, Trans);
203  }
204 
205  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind,
206  Transaction &Trans) {
207  TransformActions &TA = Pass.TA;
208 
209  // We will remove the compiler diagnostic.
210  if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
211  diag::err_arc_cast_requires_bridge,
212  E->getLocStart())) {
213  Trans.abort();
214  return;
215  }
216 
217  StringRef bridge;
218  switch(Kind) {
219  case OBC_Bridge:
220  bridge = "__bridge "; break;
221  case OBC_BridgeTransfer:
222  bridge = "__bridge_transfer "; break;
223  case OBC_BridgeRetained:
224  bridge = "__bridge_retained "; break;
225  }
226 
227  TA.clearDiagnostic(diag::err_arc_mismatched_cast,
228  diag::err_arc_cast_requires_bridge,
229  E->getLocStart());
230  if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
231  if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
232  TA.insertAfterToken(CCE->getLParenLoc(), bridge);
233  } else {
234  SourceLocation insertLoc = E->getSubExpr()->getLocStart();
235  SmallString<128> newCast;
236  newCast += '(';
237  newCast += bridge;
238  newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
239  newCast += ')';
240 
241  if (isa<ParenExpr>(E->getSubExpr())) {
242  TA.insert(insertLoc, newCast.str());
243  } else {
244  newCast += '(';
245  TA.insert(insertLoc, newCast.str());
246  TA.insertAfterToken(E->getLocEnd(), ")");
247  }
248  }
249  } else {
250  assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained);
251  SmallString<32> BridgeCall;
252 
253  Expr *WrapE = E->getSubExpr();
254  SourceLocation InsertLoc = WrapE->getLocStart();
255 
257  char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1));
258  if (Lexer::isIdentifierBodyChar(PrevChar, Pass.Ctx.getLangOpts()))
259  BridgeCall += ' ';
260 
261  if (Kind == OBC_BridgeTransfer)
262  BridgeCall += "CFBridgingRelease";
263  else
264  BridgeCall += "CFBridgingRetain";
265 
266  if (isa<ParenExpr>(WrapE)) {
267  TA.insert(InsertLoc, BridgeCall);
268  } else {
269  BridgeCall += '(';
270  TA.insert(InsertLoc, BridgeCall);
271  TA.insertAfterToken(WrapE->getLocEnd(), ")");
272  }
273  }
274  }
275 
276  void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) {
277  Transaction Trans(Pass.TA);
278  Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange());
279  rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
280  }
281 
282  void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) {
283  SourceManager &SM = Pass.Ctx.getSourceManager();
284  SourceLocation Loc = E->getExprLoc();
285  assert(Loc.isMacroID());
286  SourceLocation MacroBegin, MacroEnd;
287  std::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc);
289  SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
290  SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
291 
292  Outer = SourceRange(MacroBegin, MacroEnd);
293  Inner = SourceRange(InnerBegin, InnerEnd);
294  }
295 
296  void rewriteBlockCopyMacro(CastExpr *E) {
297  SourceRange OuterRange, InnerRange;
298  getBlockMacroRanges(E, OuterRange, InnerRange);
299 
300  Transaction Trans(Pass.TA);
301  Pass.TA.replace(OuterRange, InnerRange);
302  Pass.TA.insert(InnerRange.getBegin(), "[");
303  Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]");
304  Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
305  diag::err_arc_cast_requires_bridge,
306  OuterRange);
307  }
308 
309  void removeBlockReleaseMacro(CastExpr *E) {
310  SourceRange OuterRange, InnerRange;
311  getBlockMacroRanges(E, OuterRange, InnerRange);
312 
313  Transaction Trans(Pass.TA);
314  Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
315  diag::err_arc_cast_requires_bridge,
316  OuterRange);
317  if (!hasSideEffects(E, Pass.Ctx)) {
318  if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
319  return;
320  }
321  Pass.TA.replace(OuterRange, InnerRange);
322  }
323 
324  bool tryRemoving(Expr *E) const {
325  if (!Removables) {
326  Removables.reset(new ExprSet);
327  collectRemovables(Body, *Removables);
328  }
329 
330  if (Removables->count(E)) {
331  Pass.TA.removeStmt(E);
332  return true;
333  }
334 
335  return false;
336  }
337 
338  void transformObjCToNonObjCCast(CastExpr *E) {
339  SourceLocation CastLoc = E->getExprLoc();
340  if (CastLoc.isMacroID()) {
341  StringRef MacroName = Lexer::getImmediateMacroName(CastLoc,
342  Pass.Ctx.getSourceManager(),
343  Pass.Ctx.getLangOpts());
344  if (MacroName == "Block_copy") {
345  rewriteBlockCopyMacro(E);
346  return;
347  }
348  if (MacroName == "Block_release") {
349  removeBlockReleaseMacro(E);
350  return;
351  }
352  }
353 
354  if (isSelf(E->getSubExpr()))
355  return rewriteToBridgedCast(E, OBC_Bridge);
356 
357  CallExpr *callE;
358  if (isPassedToCFRetain(E, callE))
359  return rewriteCastForCFRetain(E, callE);
360 
361  ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr());
362  if (family == OMF_retain)
363  return rewriteToBridgedCast(E, OBC_BridgeRetained);
364 
365  if (family == OMF_autorelease || family == OMF_release) {
366  std::string err = "it is not safe to cast to '";
367  err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
368  err += "' the result of '";
369  err += family == OMF_autorelease ? "autorelease" : "release";
370  err += "' message; a __bridge cast may result in a pointer to a "
371  "destroyed object and a __bridge_retained may leak the object";
372  Pass.TA.reportError(err, E->getLocStart(),
373  E->getSubExpr()->getSourceRange());
374  Stmt *parent = E;
375  do {
376  parent = StmtMap->getParentIgnoreParenImpCasts(parent);
377  } while (parent && isa<ExprWithCleanups>(parent));
378 
379  if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
380  std::string note = "remove the cast and change return type of function "
381  "to '";
382  note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
383  note += "' to have the object automatically autoreleased";
384  Pass.TA.reportNote(note, retS->getLocStart());
385  }
386  }
387 
388  Expr *subExpr = E->getSubExpr();
389 
390  // Look through pseudo-object expressions.
391  if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
392  subExpr = pseudo->getResultExpr();
393  assert(subExpr && "no result for pseudo-object of non-void type?");
394  }
395 
396  if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
397  if (implCE->getCastKind() == CK_ARCConsumeObject)
398  return rewriteToBridgedCast(E, OBC_BridgeRetained);
399  if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
400  return rewriteToBridgedCast(E, OBC_Bridge);
401  }
402 
403  bool isConsumed = false;
404  if (isPassedToCParamWithKnownOwnership(E, isConsumed))
405  return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
406  : OBC_Bridge);
407  }
408 
409  static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
410  E = E->IgnoreParenCasts();
411  if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
412  return ME->getMethodFamily();
413 
414  return OMF_None;
415  }
416 
417  bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const {
418  if ((callE = dyn_cast_or_null<CallExpr>(
419  StmtMap->getParentIgnoreParenImpCasts(E))))
420  if (FunctionDecl *
421  FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
422  if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
423  FD->getParent()->isTranslationUnit() &&
424  FD->isExternallyVisible())
425  return true;
426 
427  return false;
428  }
429 
430  bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
431  if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
432  StmtMap->getParentIgnoreParenImpCasts(E)))
433  if (FunctionDecl *
434  FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
435  unsigned i = 0;
436  for (unsigned e = callE->getNumArgs(); i != e; ++i) {
437  Expr *arg = callE->getArg(i);
438  if (arg == E || arg->IgnoreParenImpCasts() == E)
439  break;
440  }
441  if (i < callE->getNumArgs() && i < FD->getNumParams()) {
442  ParmVarDecl *PD = FD->getParamDecl(i);
443  if (PD->hasAttr<CFConsumedAttr>()) {
444  isConsumed = true;
445  return true;
446  }
447  }
448  }
449 
450  return false;
451  }
452 
453  bool isSelf(Expr *E) const {
454  E = E->IgnoreParenLValueCasts();
455  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
456  if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
457  if (IPD->getIdentifier() == SelfII)
458  return true;
459 
460  return false;
461  }
462 };
463 
464 } // end anonymous namespace
465 
469 }
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1698
void reportNote(StringRef note, SourceLocation loc, SourceRange range=SourceRange())
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
A (possibly-)qualified type.
Definition: Type.h:653
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:2278
ObjCBridgeCastKind
The kind of bridging performed by the Objective-C bridge cast.
Stmt - This represents one statement.
Definition: Stmt.h:66
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2266
Bridging via __bridge, which does nothing but reinterpret the bits.
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1514
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument&#39;s dynamic ty...
One of these records is kept for each identifier that is lexed.
ObjCMethodFamily
A family of Objective-C methods.
bool isGlobalVar(Expr *E)
Definition: Transforms.cpp:197
void reportError(StringRef error, SourceLocation loc, SourceRange range=SourceRange())
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: Decl.h:3767
Expr * getSubExpr()
Definition: Expr.h:2761
IdentifierTable & Idents
Definition: ASTContext.h:537
const clang::PrintingPolicy & getPrintingPolicy() const
Definition: ASTContext.h:635
std::string getAsString() const
Definition: Type.h:979
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2463
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:2710
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang&#39;s AST.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Bridging via __bridge_transfer, which transfers ownership of an Objective-C pointer into ARC...
bool hasAttr() const
Definition: DeclBase.h:535
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
SourceLocation getLocEnd() const LLVM_READONLY
Definition: Stmt.cpp:290
void collectRemovables(Stmt *S, ExprSet &exprs)
Definition: Transforms.cpp:308
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
Definition: Decl.h:3689
Expr - This represents one expression.
Definition: Expr.h:106
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
const FunctionProtoType * T
void insertAfterToken(SourceLocation loc, StringRef text)
bool isObjCRetainableType() const
Definition: Type.cpp:3824
Specifies that a value-dependent expression of integral or dependent type should be considered a null...
Definition: Expr.h:702
QualType getType() const
Definition: Expr.h:128
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:1413
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:903
SourceLocation getEnd() const
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr.cast]), which uses the syntax (Type)expr.
Definition: Expr.h:2922
const SourceManager & SM
Definition: Format.cpp:1337
void rewriteUnbridgedCasts(MigrationPass &pass)
Kind
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition: Expr.h:4969
NullPointerConstantKind isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const
isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to a Null pointer constant...
Definition: Expr.cpp:3273
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
std::pair< SourceLocation, SourceLocation > getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
CastKind getCastKind() const
Definition: Expr.h:2757
bool isObjCObjectPointerType() const
Definition: Type.h:6041
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition: Expr.h:2822
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
Definition: Lexer.cpp:970
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:216
Dataflow Directional Tag Classes.
bool isRefType(QualType RetTy, StringRef Prefix, StringRef Name=StringRef())
bool isValid() const
Return true if this is a valid SourceLocation object.
bool hasSideEffects(Expr *E, ASTContext &Ctx)
Definition: Transforms.cpp:168
bool isObjCIndirectLifetimeType() const
Definition: Type.cpp:3830
Bridging via __bridge_retain, which makes an ARC object available as a +1 C pointer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
Definition: Expr.cpp:2550
bool isMacroID() const
Decl * getCalleeDecl()
Definition: Expr.cpp:1220
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Ignore parentheses and lvalue casts.
Definition: Expr.cpp:2510
SourceManager & getSourceManager()
Definition: ASTContext.h:643
static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts)
Returns true if the given character could appear in an identifier.
Definition: Lexer.cpp:1042
No particular method family.
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:989
void replace(SourceRange range, StringRef text)
TransformActions & TA
Definition: Internals.h:151
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:265
void insert(SourceLocation loc, StringRef text)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2209
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:956
bool isPointerType() const
Definition: Type.h:5944
A trivial tuple used to represent a source range.
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.cpp:277
bool hasDiagnostic(unsigned ID, SourceRange range)
Definition: Internals.h:88
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
Definition: ASTContext.h:688
This class handles loading and caching of source files into memory.