diff options
author | John Thompson <John.Thompson.JTSoftware@gmail.com> | 2013-03-27 01:02:46 +0000 |
---|---|---|
committer | John Thompson <John.Thompson.JTSoftware@gmail.com> | 2013-03-27 01:02:46 +0000 |
commit | f5db45bc16938bbd9a2935bd6704498067ec40b5 (patch) | |
tree | 603d0bc91acd0e47a3d458bf1ee492e18d13d4a0 /clang-tools-extra/modularize/Modularize.cpp | |
parent | 3901dfe431a87c71592293f579a0ec74633e1ea9 (diff) | |
download | bcm5719-llvm-f5db45bc16938bbd9a2935bd6704498067ec40b5.tar.gz bcm5719-llvm-f5db45bc16938bbd9a2935bd6704498067ec40b5.zip |
Revised to use MemoryBuffer. Removed redundant llvm:: qualifiers. Removed unnecessary c_str() calls. Reformatted with clang-format.
llvm-svn: 178104
Diffstat (limited to 'clang-tools-extra/modularize/Modularize.cpp')
-rw-r--r-- | clang-tools-extra/modularize/Modularize.cpp | 256 |
1 files changed, 139 insertions, 117 deletions
diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp index 11a82ba3ed5..af3455340cd 100644 --- a/clang-tools-extra/modularize/Modularize.cpp +++ b/clang-tools-extra/modularize/Modularize.cpp @@ -12,14 +12,15 @@ // whether the same entity (say, a NULL macro or size_t typedef) is defined in // multiple headers or whether a header produces different definitions under // different circumstances. These conditions cause modules built from the -// headers to behave poorly, and should be fixed before introducing a module +// headers to behave poorly, and should be fixed before introducing a module // map. // // Modularize takes as argument a file name for a file containing the // newline-separated list of headers to check with respect to each other. +// Lines beginning with '#' and empty lines are ignored. // Modularize also accepts regular front-end arguments. // -// Usage: modularize [-prefix (optional header path prefix)] \ +// Usage: modularize [-prefix (optional header path prefix)] // (include-files_list) [(front-end-options) ...] // // Note that unless a "-prefex (header path)" option is specified, @@ -64,11 +65,13 @@ // somewhere into Tooling/ in mainline // //===----------------------------------------------------------------------===// - + #include "llvm/Config/config.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" @@ -95,25 +98,25 @@ using namespace llvm; struct Location { const FileEntry *File; unsigned Line, Column; - - Location() : File(), Line(), Column() { } - + + Location() : File(), Line(), Column() {} + Location(SourceManager &SM, SourceLocation Loc) : File(), Line(), Column() { Loc = SM.getExpansionLoc(Loc); if (Loc.isInvalid()) return; - + std::pair<FileID, unsigned> Decomposed = SM.getDecomposedLoc(Loc); File = SM.getFileEntryForID(Decomposed.first); if (!File) return; - + Line = SM.getLineNumber(Decomposed.first, Decomposed.second); Column = SM.getColumnNumber(Decomposed.first, Decomposed.second); } - + operator bool() const { return File != 0; } - + friend bool operator==(const Location &X, const Location &Y) { return X.File == Y.File && X.Line == Y.Line && X.Column == Y.Column; } @@ -121,7 +124,7 @@ struct Location { friend bool operator!=(const Location &X, const Location &Y) { return !(X == Y); } - + friend bool operator<(const Location &X, const Location &Y) { if (X.File != Y.File) return X.File < Y.File; @@ -129,9 +132,7 @@ struct Location { return X.Line < Y.Line; return X.Column < Y.Column; } - friend bool operator>(const Location &X, const Location &Y) { - return Y < X; - } + friend bool operator>(const Location &X, const Location &Y) { return Y < X; } friend bool operator<=(const Location &X, const Location &Y) { return !(Y < X); } @@ -141,21 +142,20 @@ struct Location { }; - struct Entry { enum Kind { Tag, Value, Macro } Kind; - + Location Loc; }; struct HeaderEntry { std::string Name; Location Loc; - + friend bool operator==(const HeaderEntry &X, const HeaderEntry &Y) { return X.Loc == Y.Loc && X.Name == Y.Name; } @@ -178,106 +178,114 @@ struct HeaderEntry { typedef std::vector<HeaderEntry> HeaderContents; -class EntityMap : public llvm::StringMap<llvm::SmallVector<Entry, 2> > { +class EntityMap : public StringMap<SmallVector<Entry, 2> > { public: - llvm::DenseMap<const FileEntry *, HeaderContents> HeaderContentMismatches; - + DenseMap<const FileEntry *, HeaderContents> HeaderContentMismatches; + void add(const std::string &Name, enum Entry::Kind Kind, Location Loc) { // Record this entity in its header. HeaderEntry HE = { Name, Loc }; CurHeaderContents[Loc.File].push_back(HE); - + // Check whether we've seen this entry before. - llvm::SmallVector<Entry, 2> &Entries = (*this)[Name]; + SmallVector<Entry, 2> &Entries = (*this)[Name]; for (unsigned I = 0, N = Entries.size(); I != N; ++I) { if (Entries[I].Kind == Kind && Entries[I].Loc == Loc) return; } - + // We have not seen this entry before; record it. Entry E = { Kind, Loc }; Entries.push_back(E); } - + void mergeCurHeaderContents() { - for (llvm::DenseMap<const FileEntry *, HeaderContents>::iterator - H = CurHeaderContents.begin(), HEnd = CurHeaderContents.end(); + for (DenseMap<const FileEntry *, HeaderContents>::iterator + H = CurHeaderContents.begin(), + HEnd = CurHeaderContents.end(); H != HEnd; ++H) { // Sort contents. std::sort(H->second.begin(), H->second.end()); // Check whether we've seen this header before. - llvm::DenseMap<const FileEntry *, HeaderContents>::iterator KnownH - = AllHeaderContents.find(H->first); + DenseMap<const FileEntry *, HeaderContents>::iterator KnownH = + AllHeaderContents.find(H->first); if (KnownH == AllHeaderContents.end()) { // We haven't seen this header before; record its contents. AllHeaderContents.insert(*H); continue; } - + // If the header contents are the same, we're done. if (H->second == KnownH->second) continue; - + // Determine what changed. - std::set_symmetric_difference(H->second.begin(), H->second.end(), - KnownH->second.begin(), - KnownH->second.end(), - std::back_inserter(HeaderContentMismatches[H->first])); + std::set_symmetric_difference( + H->second.begin(), H->second.end(), KnownH->second.begin(), + KnownH->second.end(), + std::back_inserter(HeaderContentMismatches[H->first])); } - + CurHeaderContents.clear(); } private: - llvm::DenseMap<const FileEntry *, HeaderContents> CurHeaderContents; - llvm::DenseMap<const FileEntry *, HeaderContents> AllHeaderContents; + DenseMap<const FileEntry *, HeaderContents> CurHeaderContents; + DenseMap<const FileEntry *, HeaderContents> AllHeaderContents; }; -class CollectEntitiesVisitor - : public RecursiveASTVisitor<CollectEntitiesVisitor> -{ +class CollectEntitiesVisitor : + public RecursiveASTVisitor<CollectEntitiesVisitor> { public: CollectEntitiesVisitor(SourceManager &SM, EntityMap &Entities) - : SM(SM), Entities(Entities) { } - + : SM(SM), Entities(Entities) {} + bool TraverseStmt(Stmt *S) { return true; } bool TraverseType(QualType T) { return true; } bool TraverseTypeLoc(TypeLoc TL) { return true; } bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { return true; } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { return true; } - bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) { return true; } + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + return true; + } + bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) { + return true; + } bool TraverseTemplateName(TemplateName Template) { return true; } bool TraverseTemplateArgument(const TemplateArgument &Arg) { return true; } - bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { return true; } + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { + return true; + } bool TraverseTemplateArguments(const TemplateArgument *Args, - unsigned NumArgs) { return true; } + unsigned NumArgs) { + return true; + } bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { return true; } bool TraverseLambdaCapture(LambdaExpr::Capture C) { return true; } - + bool VisitNamedDecl(NamedDecl *ND) { // We only care about file-context variables. if (!ND->getDeclContext()->isFileContext()) return true; - + // Skip declarations that tend to be properly multiply-declared. if (isa<NamespaceDecl>(ND) || isa<UsingDirectiveDecl>(ND) || - isa<NamespaceAliasDecl>(ND) || - isa<ClassTemplateSpecializationDecl>(ND) || - isa<UsingDecl>(ND) || isa<UsingShadowDecl>(ND) || - isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND) || + isa<NamespaceAliasDecl>(ND) || + isa<ClassTemplateSpecializationDecl>(ND) || isa<UsingDecl>(ND) || + isa<UsingShadowDecl>(ND) || isa<FunctionDecl>(ND) || + isa<FunctionTemplateDecl>(ND) || (isa<TagDecl>(ND) && !cast<TagDecl>(ND)->isThisDeclarationADefinition())) return true; - + std::string Name = ND->getNameAsString(); if (Name.empty()) return true; - + Location Loc(SM, ND->getLocation()); if (!Loc) return true; - - Entities.add(Name, isa<TagDecl>(ND)? Entry::Tag : Entry::Value, Loc); + + Entities.add(Name, isa<TagDecl>(ND) ? Entry::Tag : Entry::Value, Loc); return true; } private: @@ -288,18 +296,18 @@ private: class CollectEntitiesConsumer : public ASTConsumer { public: CollectEntitiesConsumer(EntityMap &Entities, Preprocessor &PP) - : Entities(Entities), PP(PP) { } - + : Entities(Entities), PP(PP) {} + virtual void HandleTranslationUnit(ASTContext &Ctx) { SourceManager &SM = Ctx.getSourceManager(); - + // Collect declared entities. CollectEntitiesVisitor(SM, Entities) - .TraverseDecl(Ctx.getTranslationUnitDecl()); - + .TraverseDecl(Ctx.getTranslationUnitDecl()); + // Collect macro definitions. for (Preprocessor::macro_iterator M = PP.macro_begin(), - MEnd = PP.macro_end(); + MEnd = PP.macro_end(); M != MEnd; ++M) { Location Loc(SM, M->second->getLocation()); if (!Loc) @@ -307,7 +315,7 @@ public: Entities.add(M->first->getName().str(), Entry::Macro, Loc); } - + // Merge header contents. Entities.mergeCurHeaderContents(); } @@ -318,40 +326,43 @@ private: class CollectEntitiesAction : public SyntaxOnlyAction { public: - CollectEntitiesAction(EntityMap &Entities) : Entities(Entities) { } + CollectEntitiesAction(EntityMap &Entities) : Entities(Entities) {} protected: - virtual clang::ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) { + virtual clang::ASTConsumer * + CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { return new CollectEntitiesConsumer(Entities, CI.getPreprocessor()); } private: - EntityMap &Entities; + EntityMap &Entities; }; class ModularizeFrontendActionFactory : public FrontendActionFactory { public: - ModularizeFrontendActionFactory(EntityMap &Entities) : Entities(Entities) { } + ModularizeFrontendActionFactory(EntityMap &Entities) : Entities(Entities) {} virtual CollectEntitiesAction *create() { return new CollectEntitiesAction(Entities); } private: - EntityMap &Entities; + EntityMap &Entities; }; // Option to specify a file name for a list of header files to check. -cl::opt<std::string> ListFileName(cl::Positional, - cl::desc("<name of file containing list of headers to check>")); +cl::opt<std::string> +ListFileName(cl::Positional, + cl::desc("<name of file containing list of headers to check>")); // Collect all other arguments, which will be passed to the front end. -cl::list<std::string> CC1Arguments(cl::ConsumeAfter, - cl::desc("<arguments to be passed to front end>...")); +cl::list<std::string> CC1Arguments( + cl::ConsumeAfter, cl::desc("<arguments to be passed to front end>...")); // Option to specify a prefix to be prepended to the header names. -cl::opt<std::string> HeaderPrefix("prefix", cl::init(""), - cl::desc("Prepend header file paths with this prefix." - " If not specified," - " the files are considered to be relative to the header list file.")); +cl::opt<std::string> HeaderPrefix( + "prefix", cl::init(""), + cl::desc( + "Prepend header file paths with this prefix." + " If not specified," + " the files are considered to be relative to the header list file.")); int main(int argc, const char **argv) { @@ -365,41 +376,47 @@ int main(int argc, const char **argv) { } // By default, use the path component of the list file name. - SmallString<256> HeaderDirectory(ListFileName.c_str()); + SmallString<256> HeaderDirectory(ListFileName); sys::path::remove_filename(HeaderDirectory); - + // Get the prefix if we have one. if (HeaderPrefix.size() != 0) HeaderDirectory = HeaderPrefix; // Load the list of headers. - llvm::SmallVector<std::string, 8> Headers; + SmallVector<std::string, 32> Headers; { - std::ifstream In(ListFileName.c_str()); - if (!In) { - llvm::errs() << "Unable to open header list file \"" << ListFileName.c_str() << "\"\n"; - return 2; + OwningPtr<MemoryBuffer> listBuffer; + if (error_code ec = MemoryBuffer::getFile(ListFileName, listBuffer)) { + errs() << argv[0] << ": error: Unable to get header list '" << ListFileName + << "': " << ec.message() << '\n'; + return 1; } - std::string Line; - while (std::getline(In, Line)) { - if (Line.empty() || Line[0] == '#') + SmallVector<StringRef, 32> strings; + listBuffer->getBuffer().split(strings, "\n", -1, false); + for (SmallVectorImpl<StringRef>::iterator I = strings.begin(), + E = strings.end(); + I != E; ++I) { + StringRef line = (*I).trim(); + if (line.empty() || (line[0] == '#')) continue; SmallString<256> headerFileName; - if (sys::path::is_absolute(Line)) - headerFileName = Line; + if (sys::path::is_absolute(line)) + headerFileName = line; else { headerFileName = HeaderDirectory; - sys::path::append(headerFileName, Line); + sys::path::append(headerFileName, line); } - Headers.push_back(headerFileName.c_str()); + Headers.push_back(headerFileName.str()); } } // Create the compilation database. SmallString<256> PathBuf; - llvm::sys::fs::current_path(PathBuf); - llvm::OwningPtr<CompilationDatabase> Compilations; - Compilations.reset(new FixedCompilationDatabase(Twine(PathBuf), CC1Arguments)); + sys::fs::current_path(PathBuf); + OwningPtr<CompilationDatabase> Compilations; + Compilations.reset( + new FixedCompilationDatabase(Twine(PathBuf), CC1Arguments)); // Parse all of the headers, detecting duplicates. EntityMap Entities; @@ -414,48 +431,53 @@ int main(int argc, const char **argv) { for (unsigned I = 0, N = E->second.size(); I != N; ++I) { Location *Which; switch (E->second[I].Kind) { - case Entry::Tag: Which = &Tag; break; - case Entry::Value: Which = &Value; break; - case Entry::Macro: Which = &Macro; break; + case Entry::Tag: + Which = &Tag; + break; + case Entry::Value: + Which = &Value; + break; + case Entry::Macro: + Which = &Macro; + break; } - + if (!Which->File) { *Which = E->second[I].Loc; continue; } - - llvm::errs() << "error: '" << E->first().str().c_str() - << "' defined at both " << Which->File->getName() - << ":" << Which->Line << ":" << Which->Column - << " and " << E->second[I].Loc.File->getName() << ":" - << E->second[I].Loc.Line << ":" << E->second[I].Loc.Column << "\n"; + + errs() << "error: '" << E->first() << "' defined at both " + << Which->File->getName() << ":" << Which->Line << ":" + << Which->Column << " and " << E->second[I].Loc.File->getName() + << ":" << E->second[I].Loc.Line << ":" << E->second[I].Loc.Column + << "\n"; HadErrors = 1; } } - + // Complain about any headers that have contents that differ based on how // they are included. // FIXME: Could we provide information about which preprocessor conditionals // are involved? - for (llvm::DenseMap<const FileEntry *, HeaderContents>::iterator - H = Entities.HeaderContentMismatches.begin(), - HEnd = Entities.HeaderContentMismatches.end(); + for (DenseMap<const FileEntry *, HeaderContents>::iterator + H = Entities.HeaderContentMismatches.begin(), + HEnd = Entities.HeaderContentMismatches.end(); H != HEnd; ++H) { if (H->second.empty()) { - llvm::errs() << "internal error: phantom header content mismatch\n"; + errs() << "internal error: phantom header content mismatch\n"; continue; } - + HadErrors = 1; - llvm::errs() << "error: header '" << H->first->getName() - << "' has different contents dependening on how it was included\n"; + errs() << "error: header '" << H->first->getName() + << "' has different contents dependening on how it was included\n"; for (unsigned I = 0, N = H->second.size(); I != N; ++I) { - llvm::errs() << "note: '" << H->second[I].Name.c_str() - << "' in " << H->second[I].Loc.File->getName() << " at " - << H->second[I].Loc.Line << ":" << H->second[I].Loc.Column - << " not always provided\n"; + errs() << "note: '" << H->second[I].Name << "' in " << H->second[I] + .Loc.File->getName() << " at " << H->second[I].Loc.Line << ":" + << H->second[I].Loc.Column << " not always provided\n"; } } - + return HadErrors; } |