| //===-- LoopConvert/VariableNaming.cpp - Gererate variable names ----------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// \brief This file contains the definitino of the VariableNamer class, which |
| /// is responsible for generating new variable names and ensuring that they do |
| /// not conflict with existing ones. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "VariableNaming.h" |
| |
| using namespace llvm; |
| using namespace clang; |
| |
| std::string VariableNamer::createIndexName() { |
| // FIXME: Add in naming conventions to handle: |
| // - Uppercase/lowercase indices |
| // - How to handle conflicts |
| // - An interactive process for naming |
| std::string IteratorName; |
| std::string ContainerName; |
| if (TheContainer) |
| ContainerName = TheContainer->getName().str(); |
| |
| size_t Len = ContainerName.length(); |
| if (Len > 1 && ContainerName[Len - 1] == 's') |
| IteratorName = ContainerName.substr(0, Len - 1); |
| else |
| IteratorName = "elem"; |
| |
| if (!declarationExists(IteratorName)) |
| return IteratorName; |
| |
| IteratorName = ContainerName + "_" + OldIndex->getName().str(); |
| if (!declarationExists(IteratorName)) |
| return IteratorName; |
| |
| IteratorName = ContainerName + "_elem"; |
| if (!declarationExists(IteratorName)) |
| return IteratorName; |
| |
| IteratorName += "_elem"; |
| if (!declarationExists(IteratorName)) |
| return IteratorName; |
| |
| IteratorName = "_elem_"; |
| |
| // Someone defeated my naming scheme... |
| while (declarationExists(IteratorName)) |
| IteratorName += "i"; |
| return IteratorName; |
| } |
| |
| /// \brief Determines whether or not the the name \a Symbol conflicts with |
| /// language keywords or defined macros. Also checks if the name exists in |
| /// LoopContext, any of its parent contexts, or any of its child statements. |
| /// |
| /// We also check to see if the same identifier was generated by this loop |
| /// converter in a loop nested within SourceStmt. |
| bool VariableNamer::declarationExists(StringRef Symbol) { |
| assert(Context != nullptr && "Expected an ASTContext"); |
| IdentifierInfo &Ident = Context->Idents.get(Symbol); |
| |
| // Check if the symbol is not an identifier (ie. is a keyword or alias). |
| if (!isAnyIdentifier(Ident.getTokenID())) |
| return true; |
| |
| // Check for conflicting macro definitions. |
| if (Ident.hasMacroDefinition()) |
| return true; |
| |
| // Determine if the symbol was generated in a parent context. |
| for (const Stmt *S = SourceStmt; S != nullptr; S = ReverseAST->lookup(S)) { |
| StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(S); |
| if (I != GeneratedDecls->end() && I->second == Symbol) |
| return true; |
| } |
| |
| // FIXME: Rather than detecting conflicts at their usages, we should check the |
| // parent context. |
| // For some reason, lookup() always returns the pair (NULL, NULL) because its |
| // StoredDeclsMap is not initialized (i.e. LookupPtr.getInt() is false inside |
| // of DeclContext::lookup()). Why is this? |
| |
| // Finally, determine if the symbol was used in the loop or a child context. |
| DeclFinderASTVisitor DeclFinder(Symbol, GeneratedDecls); |
| return DeclFinder.findUsages(SourceStmt); |
| } |