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