mirror of
https://github.com/nasa/trick.git
synced 2025-06-16 22:28:18 +00:00
Fix several ICG class template bugs (#1871)
* Fix several bugs with processing templates in ICG - Fixed an issue where io_src code for some templates was being placed in the wrong file. - Fixed an issue with templates being instantiated with templates as parameters. - Fixed an issue with templates that instantiate templates. Added additional tests to cover these cases. * Moved the list of template argument header dependencies from ClassValues to PrintFileContents10 so they can be printed to the io_ file regardless of the order in which class info is printed. * Moved the list of template argument header dependencies from ClassValues to PrintFileContents10 so they can be printed to the io_ file regardless of the order in which class info is printed. Moved the list of template argument header dependencies from ClassValues to PrintFileContents10 so they can be printed to the io_ file regardless of the order in which class info is printed. * Added support to handle template enum class type argument and removed some commented code. Added support to handle template enum class type argument and removed some commented code. --------- Co-authored-by: Hong Chen <hchen99@users.noreply.github.com>
This commit is contained in:
@ -3,11 +3,20 @@ import math
|
||||
from trick.unit_test import *
|
||||
|
||||
def main():
|
||||
tso.tobj.TTT_var.aa = 1000
|
||||
tso.tobj.TTT_var.bb = 2000
|
||||
tso.tobj.TTT_var_scalar_builtins.aa = 1000
|
||||
tso.tobj.TTT_var_scalar_builtins.bb = 2000
|
||||
print ("tso.tobj.TTT_var_scalar_builtins.aa =" , tso.tobj.TTT_var_scalar_builtins.aa)
|
||||
print ("tso.tobj.TTT_var_scalar_builtins.bb =" , tso.tobj.TTT_var_scalar_builtins.bb)
|
||||
|
||||
print ("tso.tobj.TTT_var.aa =") , tso.tobj.TTT_var.aa
|
||||
print ("tso.tobj.TTT_var.bb =") , tso.tobj.TTT_var.bb
|
||||
tso.tobj.TTT_var_array_builtins.aa = [1, 2]
|
||||
tso.tobj.TTT_var_array_builtins.bb = [1.1234, 2.5678, -3.9]
|
||||
print ("tso.tobj.TTT_var_array_builtins.aa =" , tso.tobj.TTT_var_array_builtins.aa)
|
||||
print ("tso.tobj.TTT_var_array_builtins.bb =" , tso.tobj.TTT_var_array_builtins.bb)
|
||||
|
||||
tso.tobj.TTT_var_enum.aa = trick.Bar_1
|
||||
tso.tobj.TTT_var_enum.bb = [trick.Bar_1, trick.Bar_2]
|
||||
print ("tso.tobj.TTT_var_enum.aa =" , tso.tobj.TTT_var_enum.aa)
|
||||
print ("tso.tobj.TTT_var_enum.bb =" , tso.tobj.TTT_var_enum.bb)
|
||||
|
||||
trick.checkpoint_end(True)
|
||||
|
||||
|
@ -1,17 +1,25 @@
|
||||
#include "sim_objects/default_trick_sys.sm"
|
||||
|
||||
##include "trick/SimObject.hh"
|
||||
##include "TemplateTest.hh"
|
||||
##include "Potato.hh"
|
||||
##include "Onion.hh"
|
||||
##include "Foo.hh"
|
||||
##include "FooA.hh"
|
||||
|
||||
|
||||
class templateSimObject : public Trick::SimObject {
|
||||
|
||||
public:
|
||||
TemplateTest tobj ;
|
||||
potato::Potato<onion::Onion> potato;
|
||||
FooA<MyEnumClass::Enum> FooA_enum;
|
||||
|
||||
templateSimObject() {
|
||||
(1.0, "scheduled") trick_ret = print() ;
|
||||
(1.0, "scheduled") trick_ret = printMe() ;
|
||||
}
|
||||
|
||||
int print() { std::cout << "In print()" << std::endl ; return 0 ; } ;
|
||||
int printMe() { std::cout << "In printMe()" << std::endl ; return 0 ; } ;
|
||||
|
||||
} ;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
TRICK_CFLAGS += -I.
|
||||
TRICK_CXXFLAGS += -I.
|
||||
TRICK_CFLAGS += -I./models
|
||||
TRICK_CXXFLAGS += -I./models
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
@file
|
||||
|
||||
@verbatim
|
||||
PURPOSE:
|
||||
(Template tests)
|
||||
@endverbatim
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef TEMPLATETEST_HH
|
||||
#define TEMPLATETEST_HH
|
||||
|
||||
template <class A, class B>
|
||||
class TTT {
|
||||
public:
|
||||
|
||||
TTT() {
|
||||
aa = 0 ;
|
||||
bb = 0 ;
|
||||
cc = NULL ;
|
||||
dd = NULL ;
|
||||
} ;
|
||||
A aa ;
|
||||
B bb ;
|
||||
TTT<A,B> * ttt ;
|
||||
|
||||
typedef TTT<A,B> C ;
|
||||
C * cc ;
|
||||
typedef TTT<B,A> D ;
|
||||
D * dd ;
|
||||
} ;
|
||||
|
||||
class TemplateTest {
|
||||
|
||||
friend class InputProcessor ;
|
||||
friend void init_attrTemplateTest() ;
|
||||
|
||||
public:
|
||||
TTT< int , double > TTT_var ;
|
||||
|
||||
};
|
||||
|
||||
#ifdef SWIG
|
||||
%struct_str(TemplateTest)
|
||||
#endif
|
||||
|
||||
#endif /* _BALL_HH_ */
|
||||
|
30
test/SIM_test_templates/models/Foo.hh
Normal file
30
test/SIM_test_templates/models/Foo.hh
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
@file
|
||||
|
||||
@verbatim
|
||||
PURPOSE:
|
||||
(Template tests)
|
||||
@endverbatim
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef FOO_HH
|
||||
#define FOO_HH
|
||||
|
||||
class MyEnumClass {
|
||||
public:
|
||||
enum class Enum {};
|
||||
class Inner {};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Foo {
|
||||
public:
|
||||
T t; /* (--) */
|
||||
};
|
||||
|
||||
enum Bar {
|
||||
Bar_1,
|
||||
Bar_2
|
||||
};
|
||||
|
||||
#endif /* FOO_HH */
|
15
test/SIM_test_templates/models/FooA.hh
Normal file
15
test/SIM_test_templates/models/FooA.hh
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
@file
|
||||
|
||||
@verbatim
|
||||
PURPOSE:
|
||||
(Template tests)
|
||||
@endverbatim
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef FOOA_HH
|
||||
#define FOOA_HH
|
||||
|
||||
template <class T> class FooA {};
|
||||
|
||||
#endif /* FOOA_HH */
|
17
test/SIM_test_templates/models/Onion.hh
Normal file
17
test/SIM_test_templates/models/Onion.hh
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
@file
|
||||
|
||||
@verbatim
|
||||
PURPOSE:
|
||||
(Template tests)
|
||||
@endverbatim
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef ONION_HH
|
||||
#define ONION_HH
|
||||
|
||||
namespace onion {
|
||||
class Onion {};
|
||||
}
|
||||
|
||||
#endif /* ONION_HH */
|
22
test/SIM_test_templates/models/Potato.hh
Normal file
22
test/SIM_test_templates/models/Potato.hh
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
@file
|
||||
|
||||
@verbatim
|
||||
PURPOSE:
|
||||
(Template tests)
|
||||
@endverbatim
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef POTATO_HH
|
||||
#define POTATO_HH
|
||||
|
||||
namespace potato {
|
||||
template <class T>
|
||||
class Potato {
|
||||
public:
|
||||
class Inner {};
|
||||
Inner inner;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* POTATO_HH */
|
54
test/SIM_test_templates/models/TemplateTest.hh
Normal file
54
test/SIM_test_templates/models/TemplateTest.hh
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
@file
|
||||
|
||||
@verbatim
|
||||
PURPOSE:
|
||||
(Template tests)
|
||||
@endverbatim
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef TEMPLATETEST_HH
|
||||
#define TEMPLATETEST_HH
|
||||
#include "Foo.hh"
|
||||
|
||||
template <class A, class B>
|
||||
class TTT1 {
|
||||
public:
|
||||
A aa ;
|
||||
B bb ;
|
||||
TTT1<A,B> * ttt ; /* ** */
|
||||
|
||||
typedef TTT1<A,B> C ;
|
||||
C * cc ; /* ** */
|
||||
typedef TTT1<B,A> D ;
|
||||
D * dd ; /* ** */
|
||||
} ;
|
||||
|
||||
template <class T>
|
||||
class TTT2 {
|
||||
public:
|
||||
TTT1<T, int> a;
|
||||
Foo<T[3]> b;
|
||||
};
|
||||
|
||||
class TemplateTest {
|
||||
|
||||
friend class InputProcessor ;
|
||||
friend void init_attrTemplateTest() ;
|
||||
|
||||
public:
|
||||
TTT1< int , double > TTT_var_scalar_builtins ;
|
||||
TTT1< int[2] , double[3] > TTT_var_array_builtins ;
|
||||
TTT1< Bar, Bar[2] > TTT_var_enum ;
|
||||
|
||||
TTT1< Foo<int>, Foo<double[2]>[3] > TTT_var_template_parameters ;
|
||||
TTT2< Foo< TTT1< int, TTT2<char> > > > TTT_templates_of_templates ;
|
||||
|
||||
};
|
||||
|
||||
#ifdef SWIG
|
||||
%struct_str(TemplateTest)
|
||||
#endif
|
||||
|
||||
#endif /* _BALL_HH_ */
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
@ -16,6 +17,7 @@
|
||||
#include "Utilities.hh"
|
||||
#include "CommentSaver.hh"
|
||||
#include "PrintAttributes.hh"
|
||||
#include "PrintFileContents10.hh"
|
||||
#include "BraceMacro.hh"
|
||||
|
||||
extern llvm::cl::opt< int > debug_level ;
|
||||
@ -229,7 +231,7 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) {
|
||||
cval.setPOD(rec->isPOD()) ;
|
||||
|
||||
cval.setSize(rec->getASTContext().getASTRecordLayout(rec).getSize().getQuantity()) ;
|
||||
|
||||
addTemplateArgumentDependencies(rec);
|
||||
|
||||
//std::cout << "parsing " << cval.getName() << std::endl ;
|
||||
//std::cout << " [34mprocessing inheritance " << rec->getNumBases() << " " << rec->getNumVBases() << "[00m" << std::endl ;
|
||||
@ -419,3 +421,55 @@ bool CXXRecordVisitor::isPrivateEmbeddedClass( std::string in_name ) {
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
void CXXRecordVisitor::addTemplateArgumentDependencies(const clang::CXXRecordDecl *rec) {
|
||||
if (cval.getFileName() == "S_source.hh" ||
|
||||
!clang::ClassTemplateSpecializationDecl::classof(rec)) {
|
||||
return;
|
||||
}
|
||||
const auto * ctd = clang::cast<clang::ClassTemplateSpecializationDecl>(rec);
|
||||
|
||||
// Iterate over all template arguments. If any of these arguments come from an
|
||||
// external header file, make sure to #include it when generating this class's
|
||||
// io_src file.
|
||||
for (const auto & arg : ctd->getTemplateArgs().asArray()) {
|
||||
if (arg.getKind() != clang::TemplateArgument::ArgKind::Type ||
|
||||
!arg.getAsType().getTypePtrOrNull()) {
|
||||
continue;
|
||||
}
|
||||
const auto * type_ptr = arg.getAsType().getTypePtr();
|
||||
|
||||
clang::TagDecl * arg_decl = nullptr;
|
||||
switch (type_ptr->getTypeClass()) {
|
||||
case clang::Type::Record:
|
||||
arg_decl = type_ptr->getAsCXXRecordDecl();
|
||||
break;
|
||||
case clang::Type::Enum: {
|
||||
// Handle enum or enum class
|
||||
const clang::EnumType *et = type_ptr->getAs<clang::EnumType>();
|
||||
if (et) {
|
||||
arg_decl = et->getDecl();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case clang::Type::ConstantArray:
|
||||
// Will remain nullptr if this is a builtin type.
|
||||
arg_decl = type_ptr->getPointeeOrArrayElementType()->getAsCXXRecordDecl();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!arg_decl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string arg_header_file = getFileName(ci, arg_decl->getBraceRange().getEnd(), hsd);
|
||||
|
||||
pa.printer->addTemplateArgumentHeaderDependency(cval.getFileName(), arg_header_file);
|
||||
|
||||
if (debug_level >= 2) {
|
||||
std::cout << "\n\033[34mCXXRecordVisitor addTemplateArgumentDependencies "
|
||||
<< arg_header_file << "\033[0m" << std::endl ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,9 @@ class CXXRecordVisitor : public clang::RecursiveASTVisitor<CXXRecordVisitor> {
|
||||
static void addPrivateEmbeddedClass(std::string in_name) ;
|
||||
static bool isPrivateEmbeddedClass(std::string in_name) ;
|
||||
private:
|
||||
/* Save any additional #includes required by template arguments */
|
||||
void addTemplateArgumentDependencies(const clang::CXXRecordDecl *rec) ;
|
||||
|
||||
/** The compiler instance. */
|
||||
clang::CompilerInstance & ci ;
|
||||
|
||||
|
@ -290,9 +290,9 @@ bool FieldVisitor::ProcessTemplate(std::string in_name , clang::CXXRecordDecl *
|
||||
template_spec_cvis.get_class_data()->setMangledTypeName(processed_templates[in_name]) ;
|
||||
template_spec_cvis.TraverseCXXRecordDecl(crd) ;
|
||||
|
||||
// Set the actual type name and file name. Print the attributes for this template type
|
||||
// Set the actual type name. Print the attributes for this template type
|
||||
template_spec_cvis.get_class_data()->setName(in_name) ;
|
||||
template_spec_cvis.get_class_data()->setFileName(fdes->getFileName()) ;
|
||||
//template_spec_cvis.get_class_data()->setFileName(fdes->getFileName()) ;
|
||||
pa.printClass(template_spec_cvis.get_class_data()) ;
|
||||
|
||||
if ( debug_level >= 4 ) {
|
||||
|
@ -67,6 +67,9 @@ class PrintAttributes {
|
||||
bool isHeaderExcluded(const std::string& header, bool exclude_ext_libs = true);
|
||||
void markHeaderAsVisited(const std::string& header);
|
||||
|
||||
/** Version specific attributes printer */
|
||||
PrintFileContentsBase * printer ;
|
||||
|
||||
protected:
|
||||
|
||||
const bool verboseBuild = (getenv("TRICK_VERBOSE_BUILD") || getenv("VERBOSE"));
|
||||
@ -93,9 +96,6 @@ class PrintAttributes {
|
||||
/** Compiler instance */
|
||||
clang::CompilerInstance & ci ;
|
||||
|
||||
/** Version specific attributes printer */
|
||||
PrintFileContentsBase * printer ;
|
||||
|
||||
/** Force all io_src files to be written */
|
||||
bool force ;
|
||||
|
||||
|
@ -347,6 +347,8 @@ void PrintFileContents10::print_stl_helper(std::ostream & ostream , ClassValues
|
||||
}
|
||||
|
||||
void PrintFileContents10::printClass( std::ostream & ostream , ClassValues * cv ) {
|
||||
//print_template_argument_header_deps(ostream, cv) ;
|
||||
print_template_argument_header_dependencies(ostream, cv->getFileName()) ;
|
||||
print_class_attr(ostream, cv) ;
|
||||
print_stl_helper(ostream, cv) ;
|
||||
print_init_attr_func(ostream, cv) ;
|
||||
@ -416,3 +418,22 @@ void PrintFileContents10::printStlFunction(const std::string& name, const std::s
|
||||
<< " " << call << ";" << std::endl
|
||||
<< "}" << std::endl ;
|
||||
}
|
||||
|
||||
void PrintFileContents10::addTemplateArgumentHeaderDependency(const std::string& header, const std::string& dependency) {
|
||||
if (!dependency.empty()) {
|
||||
HeaderInfo header_dependency(dependency);
|
||||
template_argument_header_dependencies[header].insert(header_dependency);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintFileContents10::print_template_argument_header_dependencies(std::ostream & outfile, std::string header_file_name) {
|
||||
auto it = template_argument_header_dependencies.find(header_file_name);
|
||||
if (it != template_argument_header_dependencies.end()) {
|
||||
for (const auto& headerInfo : it->second) {
|
||||
if (!headerInfo.printed && headerInfo.header_path != header_file_name) {
|
||||
outfile << "#include \"" << headerInfo.header_path << "\"\n";
|
||||
const_cast<HeaderInfo&>(headerInfo).printed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,9 @@ class PrintFileContents10 : public PrintFileContentsBase {
|
||||
virtual void printEnumMap(std::ostream & out, EnumValues * ev) ;
|
||||
virtual void printEnumMapFooter(std::ostream & out) ;
|
||||
|
||||
/** stores template argument header dependencies to be printed */
|
||||
virtual void addTemplateArgumentHeaderDependency(const std::string& header, const std::string& dependency);
|
||||
|
||||
private:
|
||||
|
||||
/** Prints enumeration attributes */
|
||||
@ -102,6 +105,22 @@ class PrintFileContents10 : public PrintFileContentsBase {
|
||||
void print_clear_stl(std::ostream & outfile , FieldDescription * fdes , ClassValues * in_class) ;
|
||||
|
||||
void printStlFunction(const std::string& name, const std::string& parameters, const std::string& call, std::ostream& ostream, FieldDescription& fieldDescription, ClassValues& classValues);
|
||||
|
||||
/** Prints #include statements requried by tempalte arguments for the specified header */
|
||||
void print_template_argument_header_dependencies(std::ostream & outfile, std::string header_file_name) ;
|
||||
|
||||
/** Struct contains the header path and whether it's printed already */
|
||||
struct HeaderInfo {
|
||||
std::string header_path;
|
||||
bool printed;
|
||||
HeaderInfo(const std::string& path) : header_path(path), printed(false) {}
|
||||
// comparison operator for std::set
|
||||
bool operator<(const HeaderInfo& other) const {
|
||||
return header_path < other.header_path;
|
||||
}
|
||||
};
|
||||
/** The key is the header that have template argument header dependencies */
|
||||
std::map<std::string, std::set<HeaderInfo>> template_argument_header_dependencies;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
@ -45,6 +45,9 @@ class PrintFileContentsBase {
|
||||
/* gets a vector of fields that can be printed */
|
||||
std::vector<FieldDescription*> getPrintableFields(ClassValues& classValues, unsigned int ioMask = 0xFFFFFFF);
|
||||
|
||||
/** stores template argument header dependencies to be printed */
|
||||
virtual void addTemplateArgumentHeaderDependency(const std::string& header, const std::string& dependency) = 0;
|
||||
|
||||
protected:
|
||||
/** Prints the io_src_allocate function */
|
||||
virtual void print_units_map(std::ostream & ostream, ClassValues * cv) ;
|
||||
|
Reference in New Issue
Block a user