mirror of
https://github.com/nasa/trick.git
synced 2024-12-19 05:07:54 +00:00
ba75f6ff37
The call getRBraceLoc to find the ending source location of things is gone. Replaced it with getting the source range and get the end of that range. Also the way to get clang/llvm 3.9 to process c++11 code required some reordering of calls in main as well as adding some more features to be turned on.
136 lines
5.8 KiB
C++
136 lines
5.8 KiB
C++
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <libgen.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "clang/AST/RecordLayout.h"
|
|
#include "clang/Basic/FileManager.h"
|
|
|
|
#include "TranslationUnitVisitor.hh"
|
|
#include "HeaderSearchDirs.hh"
|
|
#include "ClassTemplateVisitor.hh"
|
|
#include "ClassValues.hh"
|
|
#include "ClassVisitor.hh"
|
|
#include "EnumValues.hh"
|
|
#include "EnumVisitor.hh"
|
|
#include "TypedefVisitor.hh"
|
|
#include "VariableVisitor.hh"
|
|
#include "Utilities.hh"
|
|
#include "PrintAttributes.hh"
|
|
|
|
TranslationUnitVisitor::TranslationUnitVisitor(clang::CompilerInstance & in_ci , HeaderSearchDirs & in_hsd ,
|
|
CommentSaver & in_cs , PrintAttributes & in_pa ) :
|
|
ci(in_ci) , hsd(in_hsd) , cs(in_cs) , pa(in_pa) {}
|
|
|
|
bool TranslationUnitVisitor::TraverseDecl(clang::Decl *d) {
|
|
if (!d)
|
|
return true;
|
|
if (d->isImplicit())
|
|
return true;
|
|
|
|
//std::cout << "\nTranslationUnitVisitor " << d->getDeclKindName() << std::endl ;
|
|
//d->dump() ;
|
|
|
|
switch ( d->getKind() ) {
|
|
case clang::Decl::TranslationUnit : {
|
|
TraverseTranslationUnitDecl(static_cast<clang::TranslationUnitDecl *>(d)) ;
|
|
}
|
|
break ;
|
|
case clang::Decl::CXXRecord : {
|
|
clang::CXXRecordDecl * crd = static_cast<clang::CXXRecordDecl *>(d) ;
|
|
/* The definition of the record must exist before we can process it. The definition is
|
|
NULL when this is only a forward declaration of a class */
|
|
/* Sometimes rd is not NULL when we still only have a forward declaration because
|
|
the file that defines the class is included before processing this fwd declare.
|
|
In this case the CXXRecordDecl file name will not match the current file name, and is
|
|
in fact empty */
|
|
clang::RecordDecl * rd = crd->getDefinition() ;
|
|
if ( rd != NULL ) {
|
|
std::string rd_file = getFileName(ci , rd->getSourceRange().getEnd(), hsd) ;
|
|
std::string crd_file = getFileName(ci , crd->getSourceRange().getEnd(), hsd) ;
|
|
if (!crd_file.empty() and !crd_file.compare(rd_file)) {
|
|
//crd->dump() ; std::cout << std::endl ;
|
|
if ( isInUserCode(ci , crd->getSourceRange().getEnd(), hsd) ) {
|
|
CXXRecordVisitor cvis(ci , cs, hsd , pa, true) ;
|
|
|
|
cvis.TraverseCXXRecordDecl(static_cast<clang::CXXRecordDecl *>(d)) ;
|
|
pa.printClass(cvis.get_class_data()) ;
|
|
|
|
/* Check to see if the struct/class is forward declared in the same file.
|
|
If it is, then remove the notation that it is forward declared. This
|
|
is to allow C structs to be forward declared and typedeffed and io_src
|
|
code will be generated for both the original structure name and typedeffed
|
|
name.
|
|
|
|
struct Astruct ;
|
|
typedef struct Astruct {} Bstruct ;
|
|
*/
|
|
std::set< std::string >::iterator it ;
|
|
std::string file_name = getFileName(ci , d->getLocEnd(), hsd) ;
|
|
std::string source_type = cvis.get_class_data()->getName() ;
|
|
it = fwd_declared_classes[file_name].find(source_type) ;
|
|
if ( it != fwd_declared_classes[file_name].end() ) {
|
|
fwd_declared_classes[file_name].erase(it) ;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// These are forward declarations. Insert this into the set of fwd declares keyed by the current file.
|
|
if ( ! crd->getNameAsString().empty() ) {
|
|
fwd_declared_classes[getFileName(ci , d->getLocEnd(), hsd)].insert(crd->getNameAsString()) ;
|
|
}
|
|
}
|
|
}
|
|
break ;
|
|
case clang::Decl::Enum : {
|
|
clang::EnumDecl * ed = static_cast<clang::EnumDecl *>(d) ;
|
|
if ( isInUserCode(ci , ed->getSourceRange().getEnd(), hsd) ) {
|
|
EnumVisitor evis(ci, hsd) ;
|
|
evis.TraverseDecl(ed) ;
|
|
//if ( evis.get_enum_data() != NULL ) {
|
|
pa.printEnum(evis.get_enum_data()) ;
|
|
//}
|
|
}
|
|
}
|
|
break ;
|
|
case clang::Decl::LinkageSpec : {
|
|
// This is an extern "C" block, traverse the node and the contents within the extern "C" block.
|
|
TraverseLinkageSpecDecl(static_cast<clang::LinkageSpecDecl *>(d)) ;
|
|
}
|
|
break ;
|
|
case clang::Decl::Namespace : {
|
|
TraverseNamespaceDecl(static_cast<clang::NamespaceDecl *>(d)) ;
|
|
}
|
|
break ;
|
|
case clang::Decl::ClassTemplate : {
|
|
clang::ClassTemplateDecl * ctd = static_cast<clang::ClassTemplateDecl *>(d) ;
|
|
if ( isInUserCode(ci, ctd->getSourceRange().getBegin(), hsd) ) {
|
|
clang::CXXRecordDecl * rd = ctd->getTemplatedDecl() ;
|
|
ClassTemplateVisitor ctvis(ci, cs, hsd, pa) ;
|
|
ctvis.TraverseDecl(rd) ;
|
|
}
|
|
}
|
|
break ;
|
|
case clang::Decl::Typedef : {
|
|
clang::TypedefDecl * td = static_cast<clang::TypedefDecl *>(d) ;
|
|
if ( isInUserCode(ci, td->getSourceRange().getBegin(), hsd) ) {
|
|
TypedefVisitor tv(ci , cs, hsd, pa, fwd_declared_classes[getFileName(ci , d->getLocEnd(), hsd)]) ;
|
|
tv.TraverseDecl(d) ;
|
|
}
|
|
}
|
|
break ;
|
|
case clang::Decl::Var : {
|
|
if ( isInUserCode(ci, d->getSourceRange().getBegin(), hsd) ) {
|
|
VariableVisitor tv(ci , cs, hsd, pa, fwd_declared_classes[getFileName(ci , d->getLocEnd(), hsd)]) ;
|
|
tv.TraverseDecl(d) ;
|
|
}
|
|
}
|
|
break ;
|
|
default :
|
|
break ;
|
|
}
|
|
return true ;
|
|
}
|
|
|