1 //===----------------------------------------------------------------------===//
2 //
3 // Copyright (c) 2012, 2013, 2014, 2015, 2016, 2017, 2019 The University of Utah
4 // All rights reserved.
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See the file COPYING for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #if HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 #include "ReducePointerLevel.h"
16
17 #include "clang/AST/RecursiveASTVisitor.h"
18 #include "clang/AST/ASTContext.h"
19 #include "clang/Basic/SourceManager.h"
20
21 #include "TransformationManager.h"
22
23 using namespace clang;
24
25 static const char *DescriptionMsg =
26 "Reduce pointer indirect level for a global/local variable. \
27 All valid variables are sorted by their indirect levels. \
28 The pass will ensure to first choose a valid variable \
29 with the largest indirect level. This approach could \
30 reduce the complexity of our implementation, because \
31 we don't have to consider the case where the chosen variable \
32 with the largest indirect level would be address-taken. \
33 Variables at non-largest-indirect-level are ineligible \
34 if they: \n\
35 * being address-taken \n\
36 * OR being used as LHS in any pointer form, e.g., \n\
37 p, *p(assume *p is of pointer type), \n\
38 while the RHS is NOT a UnaryOperator. \n";
39
40 static RegisterTransformation<ReducePointerLevel>
41 Trans("reduce-pointer-level", DescriptionMsg);
42
43 class PointerLevelCollectionVisitor : public
44 RecursiveASTVisitor<PointerLevelCollectionVisitor> {
45
46 public:
47
PointerLevelCollectionVisitor(ReducePointerLevel * Instance)48 explicit PointerLevelCollectionVisitor(ReducePointerLevel *Instance)
49 : ConsumerInstance(Instance)
50 { }
51
52 bool VisitDeclaratorDecl(DeclaratorDecl *DD);
53
54 bool VisitUnaryOperator(UnaryOperator *UO);
55
56 bool VisitBinaryOperator(BinaryOperator *BO);
57
58 private:
59
60 ReducePointerLevel *ConsumerInstance;
61
62 int getPointerIndirectLevel(const Type *Ty);
63
64 bool isVAArgField(DeclaratorDecl *DD);
65
66 };
67
68 class PointerLevelRewriteVisitor : public
69 RecursiveASTVisitor<PointerLevelRewriteVisitor> {
70
71 public:
72
PointerLevelRewriteVisitor(ReducePointerLevel * Instance)73 explicit PointerLevelRewriteVisitor(ReducePointerLevel *Instance)
74 : ConsumerInstance(Instance)
75 { }
76
77 bool VisitVarDecl(VarDecl *VD);
78
79 bool VisitFieldDecl(FieldDecl *FD);
80
81 bool VisitUnaryOperator(UnaryOperator *UO);
82
83 bool VisitBinaryOperator(BinaryOperator *BO);
84
85 bool VisitDeclRefExpr(DeclRefExpr *DRE);
86
87 bool VisitMemberExpr(MemberExpr *ME);
88
89 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *ME);
90
91 private:
92
93 ReducePointerLevel *ConsumerInstance;
94
95 };
96
getPointerIndirectLevel(const Type * Ty)97 int PointerLevelCollectionVisitor::getPointerIndirectLevel(const Type *Ty)
98 {
99 int IndirectLevel = 0;
100 QualType QT = Ty->getPointeeType();
101 while (!QT.isNull()) {
102 IndirectLevel++;
103 QT = QT.getTypePtr()->getPointeeType();
104 }
105 return IndirectLevel;
106 }
107
108 // Any better way to ginore these two fields
109 // coming from __builtin_va_arg ?
isVAArgField(DeclaratorDecl * DD)110 bool PointerLevelCollectionVisitor::isVAArgField(DeclaratorDecl *DD)
111 {
112 std::string Name = DD->getNameAsString();
113 return (!Name.compare("reg_save_area") ||
114 !Name.compare("overflow_arg_area"));
115 }
116
117 // I skipped IndirectFieldDecl for now
VisitDeclaratorDecl(DeclaratorDecl * DD)118 bool PointerLevelCollectionVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD)
119 {
120 if (ConsumerInstance->isInIncludedFile(DD) || isVAArgField(DD))
121 return true;
122
123 // Only consider FieldDecl and VarDecl
124 Decl::Kind K = DD->getKind();
125 if ((K != Decl::Field) && (K != Decl::Var))
126 return true;
127
128 const Type *Ty = DD->getType().getTypePtr();
129 // omit SubstTemplateTypeParmType for now, .e.g.,
130 // template <typename T>
131 // void foo(T last) { T t; }
132 // void bar(void) { int a; foo(&a); }
133 // in this example, T is inferred as int *,
134 // but we cannot do anything useful for "T t"
135 if (dyn_cast<SubstTemplateTypeParmType>(Ty))
136 return true;
137
138 if (const ArrayType *ArrayTy = dyn_cast<ArrayType>(Ty))
139 Ty = ConsumerInstance->getArrayBaseElemType(ArrayTy);
140 if (!Ty->isPointerType() || Ty->isVoidPointerType())
141 return true;
142
143 const Type *PointeeTy = Ty->getPointeeType().getTypePtr();
144 if (PointeeTy->isIncompleteType() ||
145 ConsumerInstance->isPointerToSelf(PointeeTy, DD))
146 return true;
147
148 DeclaratorDecl *CanonicalDD = dyn_cast<DeclaratorDecl>(DD->getCanonicalDecl());
149 TransAssert(CanonicalDD && "Bad DeclaratorDecl!");
150 if (ConsumerInstance->VisitedDecls.count(CanonicalDD))
151 return true;
152
153 ConsumerInstance->ValidDecls.insert(CanonicalDD);
154 ConsumerInstance->VisitedDecls.insert(CanonicalDD);
155 int IndirectLevel = getPointerIndirectLevel(Ty);
156 TransAssert((IndirectLevel > 0) && "Bad indirect level!");
157 if (IndirectLevel > ConsumerInstance->MaxIndirectLevel)
158 ConsumerInstance->MaxIndirectLevel = IndirectLevel;
159
160 ConsumerInstance->addOneDecl(CanonicalDD, IndirectLevel);
161 return true;
162 }
163
VisitUnaryOperator(UnaryOperator * UO)164 bool PointerLevelCollectionVisitor::VisitUnaryOperator(UnaryOperator *UO)
165 {
166 UnaryOperator::Opcode Op = UO->getOpcode();
167 if (Op == UO_Deref) {
168 ConsumerInstance->checkPrefixAndPostfix(UO);
169 return true;
170 }
171
172 if (Op != UO_AddrOf)
173 return true;
174
175 const Expr *SubE = UO->getSubExpr()->IgnoreParenCasts();
176 if (!dyn_cast<DeclRefExpr>(SubE) && !dyn_cast<MemberExpr>(SubE) &&
177 !dyn_cast<ArraySubscriptExpr>(SubE))
178 return true;
179
180 if (const DeclaratorDecl *DD = ConsumerInstance->getRefDecl(SubE))
181 ConsumerInstance->AddrTakenDecls.insert(DD);
182 return true;
183 }
184
VisitBinaryOperator(BinaryOperator * BO)185 bool PointerLevelCollectionVisitor::VisitBinaryOperator(BinaryOperator *BO)
186 {
187 if (!BO->isAssignmentOp() && !BO->isCompoundAssignmentOp())
188 return true;
189
190 Expr *Lhs = BO->getLHS();
191 const Type *Ty = Lhs->getType().getTypePtr();
192 if (!Ty->isPointerType())
193 return true;
194
195 Expr *Rhs = BO->getRHS()->IgnoreParenCasts();
196 if (dyn_cast<DeclRefExpr>(Rhs) ||
197 dyn_cast<UnaryOperator>(Rhs) ||
198 dyn_cast<ArraySubscriptExpr>(Rhs) ||
199 dyn_cast<MemberExpr>(Rhs) ||
200 dyn_cast<IntegerLiteral>(Rhs) ||
201 dyn_cast<CXXNewExpr>(Rhs))
202 return true;
203
204 const DeclaratorDecl *DD = ConsumerInstance->getRefDecl(Lhs);
205 TransAssert(DD && "NULL DD!");
206
207 ConsumerInstance->ValidDecls.erase(DD);
208 return true;
209 }
210
VisitFieldDecl(FieldDecl * FD)211 bool PointerLevelRewriteVisitor::VisitFieldDecl(FieldDecl *FD)
212 {
213 const FieldDecl *TheFD = dyn_cast<FieldDecl>(ConsumerInstance->TheDecl);
214 // TheDecl is a VarDecl
215 if (!TheFD)
216 return true;
217
218 const FieldDecl *CanonicalFD = dyn_cast<FieldDecl>(FD->getCanonicalDecl());
219 if (CanonicalFD == TheFD)
220 ConsumerInstance->rewriteFieldDecl(FD);
221
222 return true;
223 }
224
VisitVarDecl(VarDecl * VD)225 bool PointerLevelRewriteVisitor::VisitVarDecl(VarDecl *VD)
226 {
227 const VarDecl *TheVD = dyn_cast<VarDecl>(ConsumerInstance->TheDecl);
228 if (TheVD) {
229 const VarDecl *CanonicalVD = VD->getCanonicalDecl();
230 if (CanonicalVD == TheVD) {
231 ConsumerInstance->rewriteVarDecl(VD);
232 }
233
234 // Because VD must not be addr-taken, we don't have cases like:
235 // int **p2 = &p1;
236 // where p1 is TheVD
237 // It's safe to return from here.
238 return true;
239 }
240
241 // TheDecl is a FieldDecl.
242 // But we still need to handle VarDecls which are type of
243 // struct/union where TheField could reside, if these VarDecls
244 // have initializers
245
246 if (!VD->hasInit())
247 return true;
248
249 const Type *VDTy = VD->getType().getTypePtr();
250 if (!VDTy->isAggregateType())
251 return true;
252
253 if (const ArrayType *ArrayTy = dyn_cast<ArrayType>(VDTy)) {
254 const Type *ArrayElemTy = ConsumerInstance->getArrayBaseElemType(ArrayTy);
255 if (!ArrayElemTy->isStructureType() && !ArrayElemTy->isUnionType())
256 return true;
257 if (const RecordType *RDTy = ArrayElemTy->getAs<RecordType>()) {
258 const RecordDecl *RD = RDTy->getDecl();
259 ConsumerInstance->rewriteArrayInit(RD, VD->getInit());
260 }
261 return true;
262 }
263
264 if (const RecordType *RDTy = VDTy->getAs<RecordType>()) {
265 const RecordDecl *RD = RDTy->getDecl();
266 ConsumerInstance->rewriteRecordInit(RD, VD->getInit());
267 }
268
269 return true;
270 }
271
VisitUnaryOperator(UnaryOperator * UO)272 bool PointerLevelRewriteVisitor::VisitUnaryOperator(UnaryOperator *UO)
273 {
274 UnaryOperator::Opcode Op = UO->getOpcode();
275 if (Op != UO_Deref)
276 return true;
277
278 const Expr *SubE = UO->getSubExpr();
279 const DeclaratorDecl *DD = ConsumerInstance->getRefDecl(SubE);
280 if (DD != ConsumerInstance->TheDecl)
281 return true;
282
283 const DeclRefExpr *DRE = ConsumerInstance->getDeclRefExpr(SubE);
284 if (DRE) {
285 if (ConsumerInstance->VisitedDeclRefExprs.count(DRE))
286 return true;
287 ConsumerInstance->VisitedDeclRefExprs.insert(DRE);
288 }
289 else {
290 const MemberExpr *ME = dyn_cast<MemberExpr>(SubE);
291 if (ConsumerInstance->VisitedMemberExprs.count(ME))
292 return true;
293 ConsumerInstance->VisitedMemberExprs.insert(ME);
294 }
295
296 ConsumerInstance->rewriteDerefOp(UO);
297
298 return true;
299 }
300
VisitBinaryOperator(BinaryOperator * BO)301 bool PointerLevelRewriteVisitor::VisitBinaryOperator(BinaryOperator *BO)
302 {
303 if (!BO->isAssignmentOp() && !BO->isCompoundAssignmentOp())
304 return true;
305
306 const Expr *Lhs = BO->getLHS();
307 // Lhs could be CallExpr
308 if (dyn_cast<CallExpr>(Lhs) || dyn_cast<CXXConstructExpr>(Lhs) ||
309 dyn_cast<CXXUnresolvedConstructExpr>(Lhs))
310 return true;
311 const DeclaratorDecl *DD = ConsumerInstance->getRefDecl(Lhs);
312 // it's not always we could have a nonnull DD
313 // TransAssert(DD && "NULL DD!");
314 if (DD != ConsumerInstance->TheDecl)
315 return true;
316
317 const DeclRefExpr *DRE = ConsumerInstance->getDeclRefExpr(Lhs);
318 if (DRE) {
319 if (ConsumerInstance->VisitedDeclRefExprs.count(DRE))
320 return true;
321 ConsumerInstance->VisitedDeclRefExprs.insert(DRE);
322 }
323 else {
324 const MemberExpr *ME = dyn_cast<MemberExpr>(Lhs);
325 if (ConsumerInstance->VisitedMemberExprs.count(ME))
326 return true;
327 ConsumerInstance->VisitedMemberExprs.insert(ME);
328 }
329
330 const Expr *Rhs = BO->getRHS();
331 const Type *Ty = Lhs->getType().getTypePtr();
332 if (Ty->isPointerType()) {
333 // Prefer removing a '*' on LHS, because it's less-likely to generate
334 // bad code, e.g.,
335 // int *a, **c = &a, d, *f = &d;
336 // **c = f;
337 // if we change the code above to:
338 // **c = *f;
339 // **c is a derefence to a NULL pointer.
340 // On the other hand, *c = f is still valid.
341 const Expr *DirectLhs = Lhs->IgnoreParenCasts();
342 const UnaryOperator *LhsUO = dyn_cast<UnaryOperator>(DirectLhs);
343 if (LhsUO && (LhsUO->getOpcode() == UO_Deref)) {
344 return ConsumerInstance->RewriteHelper->removeAStarAfter(Lhs);
345 }
346
347 const Expr *DirectRhs = Rhs->IgnoreParenCasts();
348 const UnaryOperator *UO = dyn_cast<UnaryOperator>(DirectRhs);
349 if (UO && (UO->getOpcode() == UO_AddrOf)) {
350 return ConsumerInstance->RewriteHelper->removeAnAddrOfAfter(Rhs);
351 }
352
353 return ConsumerInstance->RewriteHelper->insertAStarBefore(Rhs);
354 }
355 else if (Ty->isStructureType() || Ty->isUnionType() ||
356 Ty->isIntegerType()) {
357 if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(Lhs))
358 return ConsumerInstance->RewriteHelper->removeArraySubscriptExpr(
359 ASE->getIdx());
360 else
361 return ConsumerInstance->RewriteHelper->removeAStarAfter(Lhs);
362 }
363 return true;
364 }
365
VisitDeclRefExpr(DeclRefExpr * DRE)366 bool PointerLevelRewriteVisitor::VisitDeclRefExpr(DeclRefExpr *DRE)
367 {
368 const ValueDecl *OrigDecl = DRE->getDecl();
369 if (dyn_cast<EnumConstantDecl>(OrigDecl))
370 return true;
371
372 const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(OrigDecl);
373 TransAssert(DD && "Bad VarDecl!");
374
375 if ((DD == ConsumerInstance->TheDecl) &&
376 !(ConsumerInstance->VisitedDeclRefExprs.count(DRE))) {
377 // FIXME: handle cases below
378 // int foo(void) { int *a; return a[0]; }
379 ConsumerInstance->rewriteDeclRefExpr(DRE);
380 }
381
382 return true;
383 }
384
VisitMemberExpr(MemberExpr * ME)385 bool PointerLevelRewriteVisitor::VisitMemberExpr(MemberExpr *ME)
386 {
387 if (ConsumerInstance->VisitedMemberExprs.count(ME))
388 return true;
389
390 const ValueDecl *OrigDecl = ME->getMemberDecl();
391 const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(OrigDecl);
392 if (!DD)
393 return true;
394
395 DD = dyn_cast<DeclaratorDecl>(DD->getCanonicalDecl());
396 TransAssert(DD && "Bad DeclaratorDecl!");
397 if (DD == ConsumerInstance->TheDecl) {
398 ConsumerInstance->RewriteHelper->insertAnAddrOfBefore(ME);
399 return true;
400 }
401
402 // change x->y to x.y if x is TheDecl
403 if (!ME->isArrow())
404 return true;
405
406 const Expr *Base = ME->getBase()->IgnoreParenCasts();
407 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
408 OrigDecl = DRE->getDecl();
409 DD = dyn_cast<DeclaratorDecl>(OrigDecl);
410 TransAssert(DD && "Bad VarDecl!");
411 if (DD == ConsumerInstance->TheDecl) {
412 ConsumerInstance->VisitedDeclRefExprs.insert(DRE);
413 ConsumerInstance->replaceArrowWithDot(ME);
414 }
415 return true;
416 }
417
418 if (const MemberExpr *BaseME = dyn_cast<MemberExpr>(Base)) {
419 OrigDecl = BaseME->getMemberDecl();
420 DD = dyn_cast<DeclaratorDecl>(OrigDecl);
421 TransAssert(DD && "Bad FieldDecl!");
422 if (DD == ConsumerInstance->TheDecl) {
423 ConsumerInstance->VisitedMemberExprs.insert(BaseME);
424 ConsumerInstance->replaceArrowWithDot(ME);
425 }
426 }
427
428 return true;
429 }
430
VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr * ME)431 bool PointerLevelRewriteVisitor::VisitCXXDependentScopeMemberExpr(
432 CXXDependentScopeMemberExpr *ME)
433 {
434 if (ME->isImplicitAccess())
435 return true;
436
437 const Expr *Base = ME->getBase()->IgnoreParenCasts();
438 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
439 const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DRE->getDecl());
440 TransAssert(DD && "Bad VarDecl!");
441 if (DD == ConsumerInstance->TheDecl) {
442 ConsumerInstance->VisitedDeclRefExprs.insert(DRE);
443 ConsumerInstance->replaceArrowWithDot(ME);
444 }
445 }
446 return true;
447 }
448
Initialize(ASTContext & context)449 void ReducePointerLevel::Initialize(ASTContext &context)
450 {
451 Transformation::Initialize(context);
452 CollectionVisitor = new PointerLevelCollectionVisitor(this);
453 RewriteVisitor = new PointerLevelRewriteVisitor(this);
454 }
455
HandleTranslationUnit(ASTContext & Ctx)456 void ReducePointerLevel::HandleTranslationUnit(ASTContext &Ctx)
457 {
458 CollectionVisitor->TraverseDecl(Ctx.getTranslationUnitDecl());
459 doAnalysis();
460
461 if (QueryInstanceOnly)
462 return;
463
464 if (TransformationCounter > ValidInstanceNum) {
465 TransError = TransMaxInstanceError;
466 return;
467 }
468
469 TransAssert(CollectionVisitor && "NULL CollectionVisitor!");
470 TransAssert(RewriteVisitor && "NULL CollectionVisitor!");
471 Ctx.getDiagnostics().setSuppressAllDiagnostics(false);
472 TransAssert(TheDecl && "NULL TheDecl!");
473
474 setRecordDecl();
475 RewriteVisitor->TraverseDecl(Ctx.getTranslationUnitDecl());
476
477 if (Ctx.getDiagnostics().hasErrorOccurred() ||
478 Ctx.getDiagnostics().hasFatalErrorOccurred())
479 TransError = TransInternalError;
480 }
481
doAnalysis(void)482 void ReducePointerLevel::doAnalysis(void)
483 {
484 DeclSet *Decls;
485
486 Decls = AllPtrDecls[MaxIndirectLevel];
487 if (Decls) {
488 for (DeclSet::const_iterator I = Decls->begin(), E = Decls->end();
489 I != E; ++I) {
490 if (!ValidDecls.count(*I))
491 continue;
492 ValidInstanceNum++;
493 if (TransformationCounter == ValidInstanceNum)
494 TheDecl = *I;
495 }
496 }
497
498 for (int Idx = MaxIndirectLevel - 1; Idx > 0; --Idx) {
499 Decls = AllPtrDecls[Idx];
500 if (!Decls)
501 continue;
502
503 for (DeclSet::const_iterator I = Decls->begin(), E = Decls->end();
504 I != E; ++I) {
505 if (!ValidDecls.count(*I) || AddrTakenDecls.count(*I))
506 continue;
507 ValidInstanceNum++;
508 if (TransformationCounter == ValidInstanceNum)
509 TheDecl = *I;
510 }
511 }
512 }
513
setRecordDecl(void)514 void ReducePointerLevel::setRecordDecl(void)
515 {
516 const FieldDecl *TheFD = dyn_cast<FieldDecl>(TheDecl);
517 if (!TheFD)
518 return;
519
520 TheRecordDecl = TheFD->getParent();
521 }
522
getDeclRefExpr(const Expr * Exp)523 const DeclRefExpr *ReducePointerLevel::getDeclRefExpr(const Expr *Exp)
524 {
525 const Expr *E = ignoreSubscriptExprParenCasts(Exp);
526
527 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
528 return DRE;
529
530 if (dyn_cast<MemberExpr>(E)) {
531 return NULL;
532 }
533
534 const UnaryOperator *UO = dyn_cast<UnaryOperator>(E);
535 TransAssert(UO && "Bad UnaryOperator!");
536 UnaryOperator::Opcode Op = UO->getOpcode();
537 (void)Op;
538 TransAssert(((Op == UO_Deref) || (Op == UO_AddrOf)) &&
539 "Invalid Unary Opcode!");
540 const Expr *SubE = UO->getSubExpr();
541 return getDeclRefExpr(SubE);
542 }
543
getRefDecl(const Expr * Exp)544 const DeclaratorDecl *ReducePointerLevel::getRefDecl(const Expr *Exp)
545 {
546 const Expr *E = ignoreSubscriptExprParenCasts(Exp);
547
548 if (dyn_cast<CXXThisExpr>(E))
549 return NULL;
550
551 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
552 return getCanonicalDeclaratorDecl(DRE);
553
554 if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
555 return getCanonicalDeclaratorDecl(ME);
556
557 const UnaryOperator *UO = dyn_cast<UnaryOperator>(E);
558 // In some case, E could not be of UO if the program under transformation
559 // is invalid.
560 if (!UO)
561 return NULL;
562
563 const Expr *SubE = UO->getSubExpr();
564 return getRefDecl(SubE);
565 }
566
checkPrefixAndPostfix(const UnaryOperator * UO)567 void ReducePointerLevel::checkPrefixAndPostfix(const UnaryOperator *UO)
568 {
569 const Expr *SubE = UO->getSubExpr()->IgnoreParenCasts();
570 const UnaryOperator *SubUO = dyn_cast<UnaryOperator>(SubE);
571 if (!SubUO)
572 return;
573 if (!SubUO->isPrefix() && !SubUO->isPostfix())
574 return;
575 const DeclaratorDecl *DD = getRefDecl(SubUO->getSubExpr());
576 if (DD) {
577 ValidDecls.erase(DD);
578 }
579 }
580
addOneDecl(const DeclaratorDecl * DD,int IndirectLevel)581 void ReducePointerLevel::addOneDecl(const DeclaratorDecl *DD,
582 int IndirectLevel)
583 {
584 DeclSet *DDSet = AllPtrDecls[IndirectLevel];
585 if (!DDSet) {
586 DDSet = new DeclSet();
587 AllPtrDecls[IndirectLevel] = DDSet;
588 }
589 DDSet->insert(DD);
590 }
591
592 const DeclaratorDecl *
getCanonicalDeclaratorDecl(const Expr * E)593 ReducePointerLevel::getCanonicalDeclaratorDecl(const Expr *E)
594 {
595 const DeclaratorDecl *DD = NULL;
596
597 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
598 const ValueDecl *ValueD = DRE->getDecl();
599 DD = dyn_cast<DeclaratorDecl>(ValueD);
600 if (!DD)
601 return NULL;
602 }
603 else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
604 ValueDecl *OrigDecl = ME->getMemberDecl();
605
606 // in C++, getMemberDecl returns a CXXMethodDecl.
607 TransAssert(isa<FieldDecl>(OrigDecl) && "Unsupported C++ getMemberDecl!\n");
608 DD = dyn_cast<DeclaratorDecl>(OrigDecl);
609 }
610 else {
611 TransAssert(0 && "Bad Decl!");
612 }
613
614 const DeclaratorDecl *CanonicalDD =
615 dyn_cast<DeclaratorDecl>(DD->getCanonicalDecl());
616 TransAssert(CanonicalDD && "NULL CanonicalDD!");
617 return CanonicalDD;
618 }
619
getFirstInitListElem(const InitListExpr * ILE)620 const Expr *ReducePointerLevel::getFirstInitListElem(const InitListExpr *ILE)
621 {
622 const Expr *E = NULL;
623 unsigned InitNum = ILE->getNumInits();
624 for (unsigned int I = 0; I < InitNum; ++I) {
625 E = ILE->getInit(I);
626 ILE = dyn_cast<InitListExpr>(E);
627 if (ILE) {
628 E = getFirstInitListElem(ILE);
629 }
630
631 if (E)
632 return E;
633 }
634 return NULL;
635 }
636
copyInitStr(const Expr * Exp,std::string & InitStr)637 void ReducePointerLevel::copyInitStr(const Expr *Exp,
638 std::string &InitStr)
639 {
640 const Expr *E = Exp->IgnoreParenCasts();
641
642 switch(E->getStmtClass()) {
643 case Expr::DeclRefExprClass: {
644 const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
645 const ValueDecl *OrigDecl = DRE->getDecl();
646 if (dyn_cast<FunctionDecl>(OrigDecl)) {
647 InitStr = "0";
648 return;
649 }
650
651 const VarDecl *VD = dyn_cast<VarDecl>(OrigDecl);
652 TransAssert(VD && "Bad VarDecl!");
653 const Expr *InitE = VD->getAnyInitializer();
654 if (!InitE) {
655 const Type *Ty = VD->getType().getTypePtr();
656 if (Ty->isIntegerType() || Ty->isPointerType())
657 InitStr = "0";
658 return;
659 }
660
661 const Type *VT = VD->getType().getTypePtr();
662 const ArrayType *AT = dyn_cast<ArrayType>(VT);
663 if (AT) {
664 const InitListExpr *ILE = dyn_cast<InitListExpr>(InitE);
665 if (ILE) {
666 const Expr *ElemE = getFirstInitListElem(ILE);
667 if (!ElemE)
668 return;
669 InitE = ElemE;
670 }
671 }
672 RewriteHelper->getExprString(InitE, InitStr);
673
674 return;
675 }
676
677 case Expr::ArraySubscriptExprClass: {
678 const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E);
679 if (const Expr *ElemE = getArraySubscriptElem(ASE))
680 RewriteHelper->getExprString(ElemE, InitStr);
681 return;
682 }
683
684 case Expr::MemberExprClass: {
685 const MemberExpr *ME = dyn_cast<MemberExpr>(E);
686 if (const Expr *ElemE = getMemberExprElem(ME))
687 RewriteHelper->getExprString(ElemE, InitStr);
688 return;
689 }
690
691 default:
692 TransAssert(0 && "Uncatched initializer!");
693 }
694 TransAssert(0 && "Unreachable code!");
695 }
696
getInitListExprString(const InitListExpr * ILE,std::string & NewInitStr,InitListHandler Handler)697 void ReducePointerLevel::getInitListExprString(const InitListExpr *ILE,
698 std::string &NewInitStr,
699 InitListHandler Handler)
700 {
701 unsigned int NumInits = ILE->getNumInits();
702 NewInitStr = "{";
703 for (unsigned int I = 0; I < NumInits; ++I) {
704 const Expr *SubInitE = ILE->getInit(I);
705 std::string SubInitStr("");
706 (this->*Handler)(SubInitE, SubInitStr);
707 if (SubInitStr == "") {
708 NewInitStr = "{}";
709 return;
710 }
711
712 if (I == 0)
713 NewInitStr += SubInitStr;
714 else
715 NewInitStr += ("," + SubInitStr);
716 }
717 NewInitStr += "}";
718 return;
719 }
720
getNewGlobalInitStr(const Expr * Init,std::string & InitStr)721 void ReducePointerLevel::getNewGlobalInitStr(const Expr *Init,
722 std::string &InitStr)
723 {
724 const Expr *E = Init->IgnoreParenCasts();
725
726 switch(E->getStmtClass()) {
727 case Expr::IntegerLiteralClass:
728 RewriteHelper->getExprString(Init, InitStr);
729 return;
730
731 case Expr::StringLiteralClass:
732 InitStr = 'a';
733 return;
734
735 case Expr::UnaryOperatorClass: {
736 const UnaryOperator *UO = dyn_cast<UnaryOperator>(E);
737 TransAssert((UO->getOpcode() == UO_AddrOf) && "Non-Unary Operator!");
738
739 const Expr *SubE = UO->getSubExpr();
740 TransAssert(SubE && "Bad Sub Expr!");
741 // Now we try to get the init string of this addr-taken var/array_var/field
742 copyInitStr(SubE, InitStr);
743 return;
744 }
745
746 case Expr::InitListExprClass: {
747 const InitListExpr *ILE = dyn_cast<InitListExpr>(E);
748 getInitListExprString(ILE, InitStr,
749 &ReducePointerLevel::getNewGlobalInitStr);
750 return;
751 }
752
753 case Expr::DeclRefExprClass: {
754 const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
755 copyInitStr(DRE, InitStr);
756 return;
757 }
758
759 // it could happen if E is call to a static method of a class
760 case Expr::CallExprClass: {
761 const CallExpr *CE = dyn_cast<CallExpr>(E);
762 const FunctionDecl *FD = CE->getDirectCallee();
763 TransAssert(FD && "Invalid Function Decl!");
764 const CXXMethodDecl *MDecl = dyn_cast<CXXMethodDecl>(FD); (void)MDecl;
765 TransAssert(MDecl->isStatic() && "Non static CXXMethodDecl!");
766 InitStr = "";
767 return;
768 }
769
770 case Expr::CXXNewExprClass: {
771 InitStr = "";
772 return;
773 }
774
775 default:
776 TransAssert(0 && "Uncatched initializer!");
777 }
778 TransAssert(0 && "Unreachable code!");
779 }
780
getNewLocalInitStr(const Expr * Init,std::string & InitStr)781 void ReducePointerLevel::getNewLocalInitStr(const Expr *Init,
782 std::string &InitStr)
783 {
784 const Expr *E = Init->IgnoreParenCasts();
785
786 switch(E->getStmtClass()) {
787 // catch the case like int *p = 0;
788 case Expr::IntegerLiteralClass:
789 RewriteHelper->getExprString(E, InitStr);
790 return;
791
792 // FIXME: not quite correct to set the InitStr to an empty string
793 case Expr::GNUNullExprClass:
794 InitStr = "";
795 return;
796
797 case Expr::CXXNewExprClass:
798 InitStr = "";
799 return;
800
801 case Expr::StringLiteralClass:
802 InitStr = 'a';
803 return;
804
805 case Expr::ConditionalOperatorClass:
806 InitStr = "";
807 return;
808
809 case Expr::StmtExprClass:
810 InitStr = "";
811 return;
812
813 case Expr::UnaryOperatorClass: {
814 const UnaryOperator *UO = dyn_cast<UnaryOperator>(E);
815 TransAssert(UO->getSubExpr() && "Bad Sub Expr!");
816 RewriteHelper->getExprString(E, InitStr);
817
818 size_t Pos;
819 UnaryOperator::Opcode Op = UO->getOpcode();
820 if (Op == UO_AddrOf) {
821 Pos = InitStr.find_first_of('&');
822 TransAssert((Pos != std::string::npos) && "No & operator!");
823 InitStr.erase(Pos, 1);
824 }
825 else if (Op == UO_Deref) {
826 Pos = InitStr.find_first_of('*');
827 TransAssert((Pos != std::string::npos) && "No & operator!");
828 InitStr.insert(Pos, "*");
829 }
830 else {
831 TransAssert(0 && "Bad UnaryOperator!");
832 }
833
834 return;
835 }
836
837 case Expr::DeclRefExprClass: {
838 const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(E);
839 RewriteHelper->getExprString(E, InitStr);
840
841 const Type *VT = DE->getType().getTypePtr();
842 // handle case like:
843 // int a[10];
844 // int *p = (int*)a;
845 if (const ArrayType *AT = dyn_cast<ArrayType>(VT)) {
846 unsigned int Dim = getArrayDimension(AT);
847 std::string ArrayElemsStr("");
848 for (unsigned int I = 0; I < Dim; ++I) {
849 ArrayElemsStr += "[0]";
850 }
851 InitStr += ArrayElemsStr;
852 }
853 else {
854 InitStr = "*" + InitStr;
855 }
856 return;
857 }
858
859 case Expr::MemberExprClass: // Fall-through
860 case Expr::BinaryOperatorClass:
861 case Expr::CXXMemberCallExprClass:
862 case Expr::CallExprClass:
863 case Expr::ArraySubscriptExprClass: {
864 RewriteHelper->getExprString(E, InitStr);
865 InitStr = "*(" + InitStr + ")";
866 return;
867 }
868
869 case Expr::InitListExprClass: {
870 const InitListExpr *ILE = dyn_cast<InitListExpr>(E);
871 getInitListExprString(ILE, InitStr,
872 &ReducePointerLevel::getNewLocalInitStr);
873 return;
874 }
875
876 default:
877 TransAssert(0 && "Uncaught initializer!");
878 }
879
880 TransAssert(0 && "Unreachable code!");
881 }
882
rewriteVarDecl(const VarDecl * VD)883 void ReducePointerLevel::rewriteVarDecl(const VarDecl *VD)
884 {
885 RewriteHelper->removeAStarBefore(VD);
886 const Expr *Init = VD->getInit();
887 if (!Init)
888 return;
889
890 const Type *Ty = VD->getType().getTypePtr();
891 if (Ty->isPointerType()) {
892 const Type *PointeeTy = Ty->getPointeeType().getTypePtr();
893 if (PointeeTy->isRecordType()) {
894 const Expr *E = Init->IgnoreParenCasts();
895 Expr::StmtClass SC = E->getStmtClass();
896 if ((SC == Expr::IntegerLiteralClass) ||
897 (SC == Expr::StringLiteralClass)) {
898 RewriteHelper->removeVarInitExpr(VD);
899 return;
900 }
901 }
902 }
903
904 std::string NewInitStr("");
905 if (VD->hasLocalStorage()) {
906 getNewLocalInitStr(Init, NewInitStr);
907 }
908 else {
909 // Global var cannot have non-const initializer,
910 // e.g., "int *p = &g;" ==> "int p = g" is invalid.
911 // So we need to do more work.
912 // Get the init string of RHS var:
913 // The transformation will look like:
914 // (1) int g = 1;
915 // int *p = &g; ==> int p = 1;
916 // (2) int g[2] = {1, 2};
917 // int *p = &g[1]; ==> int p = 2;
918 // (2) int g[2] = {1, 2};
919 // int *p = &g; ==> int p = 1;
920 // (4) struct S g = {1, 2};
921 // int *p = &g.f1; ==> int p = 1;
922 getNewGlobalInitStr(Init, NewInitStr);
923 }
924
925 if (NewInitStr.empty())
926 RewriteHelper->removeVarInitExpr(VD);
927 else
928 RewriteHelper->replaceExpr(Init, NewInitStr);
929 }
930
rewriteFieldDecl(const FieldDecl * FD)931 void ReducePointerLevel::rewriteFieldDecl(const FieldDecl *FD)
932 {
933 RewriteHelper->removeAStarBefore(FD);
934 }
935
rewriteDerefOp(const UnaryOperator * UO)936 void ReducePointerLevel::rewriteDerefOp(const UnaryOperator *UO)
937 {
938 RewriteHelper->removeAStarAfter(UO);
939 }
940
rewriteDeclRefExpr(const DeclRefExpr * DRE)941 void ReducePointerLevel::rewriteDeclRefExpr(const DeclRefExpr *DRE)
942 {
943 RewriteHelper->insertAnAddrOfBefore(DRE);
944 }
945
replaceArrowWithDot(const Expr * E)946 void ReducePointerLevel::replaceArrowWithDot(const Expr *E)
947 {
948 std::string ES;
949 RewriteHelper->getExprString(E, ES);
950 SourceLocation LocStart = E->getBeginLoc();
951
952 size_t ArrowPos = ES.find("->");
953 TransAssert((ArrowPos != std::string::npos) && "Cannot find Arrow!");
954 LocStart = LocStart.getLocWithOffset(ArrowPos);
955 TheRewriter.ReplaceText(LocStart, 2, ".");
956 }
957
isPointerToSelf(const Type * Ty,const DeclaratorDecl * DD)958 bool ReducePointerLevel::isPointerToSelf(const Type *Ty,
959 const DeclaratorDecl *DD)
960 {
961 const RecordType *RTy = Ty->getAs<RecordType>();
962 if (!RTy)
963 return false;
964
965 const DeclContext *Ctx = DD->getDeclContext();
966 const RecordDecl *RD = dyn_cast<RecordDecl>(Ctx);
967 if (!RD)
968 return false;
969
970 const RecordDecl *NestedRD = RTy->getDecl();
971 return (RD->getCanonicalDecl() == NestedRD->getCanonicalDecl());
972 }
973
rewriteRecordInit(const RecordDecl * RD,const Expr * Init)974 void ReducePointerLevel::rewriteRecordInit(const RecordDecl *RD,
975 const Expr *Init)
976 {
977 // FIXME: Csmith doesn't have pointer fields, I will
978 // leave this function as future work
979 }
980
rewriteArrayInit(const RecordDecl * RD,const Expr * Init)981 void ReducePointerLevel::rewriteArrayInit(const RecordDecl *RD,
982 const Expr *Init)
983 {
984 // FIXME: Csmith doesn't have pointer fields, I will
985 // leave this function as future work
986 }
987
~ReducePointerLevel(void)988 ReducePointerLevel::~ReducePointerLevel(void)
989 {
990 delete CollectionVisitor;
991 delete RewriteVisitor;
992
993 for (LevelToDeclMap::iterator I = AllPtrDecls.begin(),
994 E = AllPtrDecls.end(); I != E; ++I) {
995 delete (*I).second;
996 }
997 }
998
999