1 //===----------------------------------------------------------------------===//
2 //
3 // Copyright (c) 2012 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 #ifndef REMOVE_NAMESPACE_H
12 #define REMOVE_NAMESPACE_H
13 
14 #include <string>
15 #include "Transformation.h"
16 #include "llvm/ADT/SmallPtrSet.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "clang/AST/NestedNameSpecifier.h"
19 
20 namespace clang {
21   class DeclGroupRef;
22   class ASTContext;
23   class NamespaceDecl;
24   class NamedDecl;
25   class DeclContext;
26   class UsingDirectiveDecl;
27   class UsingShadowDecl;
28   class UsingDecl;
29   class EnumDecl;
30 }
31 
32 class RemoveNamespaceASTVisitor;
33 class RemoveNamespaceRewriteVisitor;
34 
35 class RemoveNamespace : public Transformation {
36 friend class RemoveNamespaceASTVisitor;
37 friend class RemoveNamespaceRewriteVisitor;
38 
39 public:
40 
RemoveNamespace(const char * TransName,const char * Desc)41   RemoveNamespace(const char *TransName, const char *Desc)
42     : Transformation(TransName, Desc),
43       CollectionVisitor(NULL),
44       RewriteVisitor(NULL),
45       TheNamespaceDecl(NULL),
46       NamePrefix("Trans_NS_"),
47       AnonNamePrefix("Trans_Anon_NS"),
48       AnonNamespaceCounter(0),
49       isForUsingNamedDecls(false)
50   { }
51 
52   ~RemoveNamespace(void);
53 
54 private:
55 
56   typedef llvm::SmallPtrSet<const clang::NamespaceDecl *, 15> NamespaceDeclSet;
57 
58   typedef llvm::SmallPtrSet<const clang::UsingDecl *, 10> UsingDeclSet;
59 
60   typedef llvm::SmallPtrSet<const clang::UsingDirectiveDecl *, 10>
61             UsingDirectiveDeclSet;
62 
63   typedef llvm::DenseMap<const clang::NamedDecl *, std::string>
64             NamedDeclToNameMap;
65 
66   virtual void Initialize(clang::ASTContext &context);
67 
68   virtual bool HandleTopLevelDecl(clang::DeclGroupRef D);
69 
70   virtual void HandleTranslationUnit(clang::ASTContext &Ctx);
71 
72   void addNamedDeclsFromNamespace(const clang::NamespaceDecl *ND);
73 
74   bool handleOneNamespaceDecl(clang::NamespaceDecl *ND);
75 
76   void removeNamespace(const clang::NamespaceDecl *ND);
77 
78   void removeUsingOrUsingDirectiveDecl(const clang::Decl *D);
79 
80   void handleOneNamedDecl(const clang::NamedDecl *ND,
81                           const clang::DeclContext *ParentCtx,
82                           const std::string &NamespaceName);
83 
84   bool hasNameConflict(const clang::NamedDecl *ND,
85                        const clang::DeclContext *ParentCtx);
86 
87   bool isValidNamedDeclKind(const clang::NamedDecl *ND);
88 
89   void handleOneEnumDecl(const clang::EnumDecl *ED,
90                          const std::string &Prefix,
91                          NamedDeclToNameMap &NameMap,
92                          const clang::DeclContext *ParentCtx);
93 
94   void handleOneUsingShadowDecl(const clang::UsingShadowDecl *UD,
95                                 const clang::DeclContext *ParentCtx);
96 
97   void handleOneUsingDirectiveDecl(const clang::UsingDirectiveDecl *UD,
98                                    const clang::DeclContext *ParentCtx);
99 
100   void rewriteNamedDecls(void);
101 
102   bool getNewNameFromNameMap(const clang::NamedDecl *ND,
103                              std::string &Name,
104                              const NamedDeclToNameMap &NameMap);
105 
106   bool getNewNameByNameFromNameMap(const std::string &Name,
107                                    std::string &NewName,
108                                    const NamedDeclToNameMap &NameMap);
109 
110   bool getNewNamedDeclName(const clang::NamedDecl *ND, std::string &Name);
111 
112   bool getNewUsingNamedDeclName(const clang::NamedDecl *ND, std::string &Name);
113 
114   bool getNewName(const clang::NamedDecl *ND, std::string &Name);
115 
116   bool getNewNameByName(const std::string &Name, std::string &NewName);
117 
118   bool isGlobalNamespace(clang::NestedNameSpecifierLoc Loc);
119 
120   bool isTheNamespaceSpecifier(const clang::NestedNameSpecifier *NNS);
121 
122   void removeLastNamespaceFromUsingDecl(const clang::UsingDirectiveDecl *D,
123                                         const clang::NamespaceDecl *ND);
124 
125   void replaceFirstNamespaceFromUsingDecl(const clang::UsingDirectiveDecl *D,
126                                           const std::string &Name);
127 
128   bool isSuffix(std::string &Name, std::string &SpecifierName);
129 
130   NamespaceDeclSet VisitedND;
131 
132   UsingDeclSet UselessUsingDecls;
133 
134   UsingDirectiveDeclSet UselessUsingDirectiveDecls;
135 
136   // a mapping from NamedDecls in TheNamespaceDecl used in TheNamespaceDecl
137   // to their new names after TheNamespaceDecl is removed. This map only
138   // stores those NamedDecls which need to be renamed.
139   NamedDeclToNameMap NamedDeclToNewName;
140 
141   // a mapping from NamedDecl in other namespaces used in TheNamespaceDecl
142   // to their new names after TheNamespaceDecl is removed.
143   NamedDeclToNameMap UsingNamedDeclToNewName;
144 
145   RemoveNamespaceASTVisitor *CollectionVisitor;
146 
147   RemoveNamespaceRewriteVisitor *RewriteVisitor;
148 
149   clang::NamespaceDecl *TheNamespaceDecl;
150 
151   const std::string NamePrefix;
152 
153   // Prefix for anonymous namespaces
154   const std::string AnonNamePrefix;
155 
156   unsigned AnonNamespaceCounter;
157 
158   // a flag to indicate if we are working on renaming UsingNamedDecl
159   // The purpose of this flag is to avoid double visit.
160   // The RemoveNamespaceRewriteVisitor are used twice:
161   // * one for TheNamespaceDecl. In this case, we only rename UsingNamedDecls
162   //   without doing any other work
163   // * another is for NamedDecls belonging to TheNamespaceDecl
164   bool isForUsingNamedDecls;
165 
166   // Unimplemented
167   RemoveNamespace(void);
168 
169   RemoveNamespace(const RemoveNamespace &);
170 
171   void operator=(const RemoveNamespace &);
172 };
173 #endif
174