// This file is part of the AspectC++ compiler 'ac++'. // Copyright (C) 1999-2003 The 'ac++' developers (see aspectc.org) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this program; if not, write to the Free // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, // MA 02111-1307 USA #include "ClangIncludeExpander.h" #include "ClangIncludeExpander.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Rewrite/Frontend/Rewriters.h" #include "llvm/Support/raw_os_ostream.h" void ClangIncludeExpander::expand(std::ostream &out) { // Setup the strategy object that decides whether an include should be // expanded. struct ProjectStrategy : public clang::FileExpansionStrategy { ClangIncludeExpander &_ie; ProjectStrategy(ClangIncludeExpander &ie) : _ie(ie) {} virtual bool should_expand_file(clang::FileID From, clang::FileID To) { clang::SourceManager &sm = _ie._project.get_compiler_instance()->getSourceManager(); // Check if From and To are coming from this project. const char *from_name = sm.getFileEntryForID(From)->getName(); const char *to_name = sm.getFileEntryForID(To)->getName(); bool from_below = _ie._project.isBelow(from_name); bool to_below = _ie._project.isBelow(to_name); if (!from_below && to_below) { // oops, an external file includes an internal => error! _ie._err << Puma::sev_error //<< this_token.location () << "internal file '" << to_name << "' is included by external '" << from_name << "'" << Puma::endMessage; } return to_below; } }; clang::CompilerInstance *ci = _project.get_compiler_instance(); if (!ci) return; // No compiler, nothing to do! // Create a new PP to get rid of old state. ci->createPreprocessor(); ci->getDiagnosticClient().BeginSourceFile(ci->getLangOpts(), &ci->getPreprocessor()); // Now call Clang's include rewriter to do the heavy lifting. llvm::raw_os_ostream osos(out); ProjectStrategy s(*this); clang::RewriteIncludesInInput(ci->getPreprocessor(), &osos, ci->getPreprocessorOutputOpts(), &s); }