1 //===----------------------------------------------------------------------===//
2 //
3 // Copyright (c) 2012, 2013, 2015, 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 "ReplaceOneLevelTypedefType.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 "This pass literally replaces a typedef type with the underlying type \
27 if typedef type is only been used once. It doesn't recursively resolve \
28 the underlying type.";
29 
30 static RegisterTransformation<ReplaceOneLevelTypedefType>
31          Trans("replace-one-level-typedef-type", DescriptionMsg);
32 
33 class ReplaceOneLevelTypedefTypeCollectionVisitor : public
34   RecursiveASTVisitor<ReplaceOneLevelTypedefTypeCollectionVisitor> {
35 
36 public:
ReplaceOneLevelTypedefTypeCollectionVisitor(ReplaceOneLevelTypedefType * Instance)37   explicit ReplaceOneLevelTypedefTypeCollectionVisitor(
38              ReplaceOneLevelTypedefType *Instance)
39     : ConsumerInstance(Instance)
40   { }
41 
42   bool VisitTypedefTypeLoc(TypedefTypeLoc TLoc);
43 
44 private:
45   ReplaceOneLevelTypedefType *ConsumerInstance;
46 };
47 
VisitTypedefTypeLoc(TypedefTypeLoc TLoc)48 bool ReplaceOneLevelTypedefTypeCollectionVisitor::VisitTypedefTypeLoc(
49        TypedefTypeLoc TLoc)
50 {
51   ConsumerInstance->handleOneTypedefTypeLoc(TLoc);
52   return true;
53 }
54 
Initialize(ASTContext & context)55 void ReplaceOneLevelTypedefType::Initialize(ASTContext &context)
56 {
57   Transformation::Initialize(context);
58   CollectionVisitor = new ReplaceOneLevelTypedefTypeCollectionVisitor(this);
59 }
60 
HandleTranslationUnit(ASTContext & Ctx)61 void ReplaceOneLevelTypedefType::HandleTranslationUnit(ASTContext &Ctx)
62 {
63   CollectionVisitor->TraverseDecl(Ctx.getTranslationUnitDecl());
64   analyzeTypeLocs();
65 
66   if (QueryInstanceOnly)
67     return;
68 
69   if (TransformationCounter > ValidInstanceNum) {
70     TransError = TransMaxInstanceError;
71     return;
72   }
73 
74   Ctx.getDiagnostics().setSuppressAllDiagnostics(false);
75   TransAssert(TheTypedefDecl && "NULL TheTypedefDecl!");
76   rewriteTypedefType();
77   removeTypedefs();
78 
79   if (Ctx.getDiagnostics().hasErrorOccurred() ||
80       Ctx.getDiagnostics().hasFatalErrorOccurred())
81     TransError = TransInternalError;
82 }
83 
analyzeTypeLocs()84 void ReplaceOneLevelTypedefType::analyzeTypeLocs()
85 {
86   for (TypedefDeclToRefMap::iterator I = AllTypeDecls.begin(),
87        E = AllTypeDecls.end(); I != E; ++I) {
88     TypedefTypeLocVector *LocVec = (*I).second;
89     if (LocVec->size() > 1)
90       continue;
91     ValidInstanceNum++;
92     if (ValidInstanceNum == TransformationCounter) {
93       TheTypedefDecl = (*I).first;
94       TheTypeLoc = LocVec->back();
95     }
96   }
97 }
98 
rewriteTypedefType()99 void ReplaceOneLevelTypedefType::rewriteTypedefType()
100 {
101   std::string NewTyStr;
102   TheTypedefDecl->getUnderlyingType().getAsStringInternal(NewTyStr,
103                                         Context->getPrintingPolicy());
104   SourceRange Range = TheTypeLoc.getSourceRange();
105   TheRewriter.ReplaceText(Range, NewTyStr);
106 }
107 
removeTypedefs()108 void ReplaceOneLevelTypedefType::removeTypedefs()
109 {
110   for (TypedefDecl::redecl_iterator I = TheTypedefDecl->redecls_begin(),
111        E = TheTypedefDecl->redecls_end(); I != E; ++I) {
112     SourceRange Range = (*I)->getSourceRange();
113     if (Range.isValid()) {
114       RewriteHelper->removeTextUntil(Range, ';');
115       Rewritten = true;
116     }
117   }
118 }
119 
handleOneTypedefTypeLoc(TypedefTypeLoc TLoc)120 void ReplaceOneLevelTypedefType::handleOneTypedefTypeLoc(TypedefTypeLoc TLoc)
121 {
122   if (isInIncludedFile(TLoc.getBeginLoc()))
123     return;
124   const TypedefType *TdefTy = TLoc.getTypePtr();
125   const TypedefDecl *TdefD = dyn_cast<TypedefDecl>(TdefTy->getDecl());
126   if (!TdefD || TdefD->getBeginLoc().isInvalid())
127     return;
128   const TypedefDecl *CanonicalD =
129     dyn_cast<TypedefDecl>(TdefD->getCanonicalDecl());
130 
131   TypedefTypeLocVector *LocVec = AllTypeDecls[CanonicalD];
132   if (!LocVec) {
133     LocVec = new TypedefTypeLocVector();
134     TransAssert(LocVec && "NULL LocVec!");
135     AllTypeDecls[CanonicalD] = LocVec;
136   }
137   LocVec->push_back(TLoc);
138 }
139 
~ReplaceOneLevelTypedefType(void)140 ReplaceOneLevelTypedefType::~ReplaceOneLevelTypedefType(void)
141 {
142   for (TypedefDeclToRefMap::iterator I = AllTypeDecls.begin(),
143        E = AllTypeDecls.end(); I != E; ++I) {
144     delete (*I).second;
145   }
146   delete CollectionVisitor;
147 }
148 
149