Skip to content

Commit

Permalink
Added support for expansion of class templates.
Browse files Browse the repository at this point in the history
Up to now class templates ended up with just the class tag and name.
This change expands the whole class, including methods and variables.
There are some cases where a method has no body in the expanded version.
In that case this method is unused in the instatiated version.

This changes also brings support for more statements/expressions. Like
the placement delete or inline variable initialization.

A further simplification is the attempt to introduce a function which is
responsible to adding parens or curlys.
  • Loading branch information
Andreas Fertig authored and Andreas Fertig committed Jun 16, 2018
1 parent 6de3d9c commit 86d8bd9
Show file tree
Hide file tree
Showing 73 changed files with 1,388 additions and 256 deletions.
498 changes: 395 additions & 103 deletions CodeGenerator.cpp

Large diffs are not rendered by default.

22 changes: 21 additions & 1 deletion CodeGenerator.h
Expand Up @@ -105,6 +105,8 @@ class CodeGenerator

virtual ~CodeGenerator() = default;

#define IGNORED_DECL(type) \
virtual void InsertArg(const type*) {}
#define IGNORED_STMT(type) \
virtual void InsertArg(const type*) {}
#define SUPPORTED_DECL(type) virtual void InsertArg(const type* stmt);
Expand All @@ -126,10 +128,12 @@ class CodeGenerator
}

STRONG_BOOL(SkipConstexpr);
STRONG_BOOL(SkipAccess);

static void InsertAccessModifierAndNameWithReturnType(OutputFormatHelper& outputFormatHelper,
const CXXMethodDecl& decl,
SkipConstexpr skipConstexpr = SkipConstexpr::No);
const SkipConstexpr skipConstexpr = SkipConstexpr::No,
const SkipAccess skipAccess = SkipAccess::No);

protected:
void HandleCharacterLiteral(const CharacterLiteral& stmt);
Expand Down Expand Up @@ -160,6 +164,22 @@ class CodeGenerator
void InsertTemplateArgs(const ArrayRef<TemplateArgument>& array);
void InsertTemplateArg(const TemplateArgument& arg);

/// \brief Check whether or not this statement will add curlys or parentheses and add them only if required.
void InsertCurlysIfRequired(const Stmt* stmt);

STRONG_BOOL(AddSpaceAtTheEnd);

enum class BraceKind
{
Parens,
Curlys
};

template<typename T>
void WrapInParensOrCurlys(const BraceKind curlys,
T&& lambda,
const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);

static const char* GetKind(const UnaryExprOrTypeTraitExpr& uk);
static const char* GetOpcodeName(const int kind);
static const char* GetBuiltinTypeSuffix(const BuiltinType& type);
Expand Down
11 changes: 10 additions & 1 deletion CodeGeneratorTypes.h
Expand Up @@ -17,13 +17,22 @@
IGNORED_STMT(OMPOrderedDirective)
IGNORED_STMT(OMPParallelForDirective)

IGNORED_DECL(StaticAssertDecl)
IGNORED_DECL(UsingShadowDecl)
IGNORED_DECL(UsingPackDecl)

SUPPORTED_DECL(DecompositionDecl)
SUPPORTED_DECL(VarDecl)
SUPPORTED_DECL(TypeAliasDecl)
SUPPORTED_DECL(TypedefDecl)
SUPPORTED_DECL(StaticAssertDecl)
SUPPORTED_DECL(FieldDecl)
SUPPORTED_DECL(AccessSpecDecl)
SUPPORTED_DECL(CXXMethodDecl)
SUPPORTED_DECL(UsingDecl)
SUPPORTED_DECL(CXXRecordDecl)

SUPPORTED_STMT(CXXDeleteExpr)
SUPPORTED_STMT(CXXDefaultInitExpr)
SUPPORTED_STMT(MemberExpr)
SUPPORTED_STMT(IntegerLiteral)
SUPPORTED_STMT(StringLiteral)
Expand Down
2 changes: 2 additions & 0 deletions InsightsBase.h
Expand Up @@ -33,8 +33,10 @@ class InsightsBase

STRONG_BOOL(SkipConstexpr);

public:
static void GenerateFunctionPrototype(OutputFormatHelper& outputFormatHelper, const FunctionDecl& FD);

protected:
bool SkipIfAlreadySeen(const Stmt* stmt);

private:
Expand Down
34 changes: 34 additions & 0 deletions NumberIterator.h
@@ -0,0 +1,34 @@
#ifndef INSIGHTS_NUMBER_ITERATOR_H
#define INSIGHTS_NUMBER_ITERATOR_H

template<typename T>
class NumberIterator
{
public:
NumberIterator(const T num)
: mNum{num}
, mCount{0}
{
}

const T& operator*() const { return mCount; }

NumberIterator& operator++()
{
++mCount;

return *this;
}

bool operator!=(const NumberIterator&) const { return mCount < mNum; }

const NumberIterator& begin() const { return *this; }
const NumberIterator& end() const { return *this; }

private:
const T mNum;
T mCount;
};
//-----------------------------------------------------------------------------

#endif /* INSIGHTS_NUMBER_ITERATOR_H */
17 changes: 8 additions & 9 deletions StaticAssertHandler.cpp
Expand Up @@ -6,6 +6,7 @@
****************************************************************************/

#include "StaticAssertHandler.h"
#include "CodeGenerator.h"
#include "InsightsHelpers.h"
#include "InsightsMatchers.h"
#include "InsightsStaticStrings.h"
Expand All @@ -30,17 +31,15 @@ StaticAssertHandler::StaticAssertHandler(Rewriter& rewrite, MatchFinder& matcher

void StaticAssertHandler::run(const MatchFinder::MatchResult& result)
{
const auto* matchedDecl = result.Nodes.getNodeAs<StaticAssertDecl>("static_assert");
const std::string passFailed = [&]() {
if(!matchedDecl->isFailed()) {
return "/* PASSED: ";
}
if(const auto* matchedDecl = result.Nodes.getNodeAs<StaticAssertDecl>("static_assert")) {
OutputFormatHelper outputFormatHelper{};
CodeGenerator codeGenerator{outputFormatHelper};
codeGenerator.InsertArg(matchedDecl);

return "/* FAILED: ";
}();
const auto sr = GetSourceRangeAfterToken(matchedDecl->getSourceRange(), tok::semi, result);

mRewrite.InsertText(matchedDecl->getLocStart(), passFailed);
mRewrite.InsertTextAfterToken(matchedDecl->getLocEnd(), "*/");
mRewrite.ReplaceText(sr, outputFormatHelper.GetString());
}
}
//-----------------------------------------------------------------------------

Expand Down
16 changes: 5 additions & 11 deletions TemplateHandler.cpp
Expand Up @@ -44,6 +44,10 @@ void TemplateHandler::run(const MatchFinder::MatchResult& result)
InsertInstantiatedTemplate(*functionDecl, result);

} else if(const auto* clsTmplSpecDecl = result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("class")) {
// skip classes/struct's without a definition
if(!clsTmplSpecDecl->hasDefinition()) {
return;
}

OutputFormatHelper outputFormatHelper{};
outputFormatHelper.AppendNewLine();
Expand All @@ -53,19 +57,9 @@ void TemplateHandler::run(const MatchFinder::MatchResult& result)

outputFormatHelper.AppendNewLine("#ifdef INSIGHTS_USE_TEMPLATE");

outputFormatHelper.Append(kwClassSpace, GetName(*clsTmplSpecDecl));

CodeGenerator codeGenerator{outputFormatHelper};
codeGenerator.InsertTemplateArgs(*clsTmplSpecDecl);

outputFormatHelper.AppendNewLine();

outputFormatHelper.OpenScope();
codeGenerator.InsertArg(clsTmplSpecDecl);

outputFormatHelper.CloseScopeWithSemi();
outputFormatHelper.AppendNewLine();

outputFormatHelper.AppendNewLine();
outputFormatHelper.AppendNewLine("#endif");

const auto* clsTmplDecl = result.Nodes.getNodeAs<ClassTemplateDecl>("decl");
Expand Down
1 change: 1 addition & 0 deletions scripts/travis_install.sh
Expand Up @@ -2,6 +2,7 @@

if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
export HOMEBREW_NO_AUTO_UPDATE=1
brew update > /dev/null
brew install cmake || brew upgrade cmake
brew install xz || brew upgrade xz

Expand Down
10 changes: 10 additions & 0 deletions tests/AutoHandler5Test.cpp
@@ -0,0 +1,10 @@
int foo(int a,int b){ return a+b; }

int main(){
if(true) {
int (*add)(int,int)= foo;
// auto within a function pointer
auto add1= foo;
}
}

12 changes: 12 additions & 0 deletions tests/AutoHandler5Test.expect
@@ -0,0 +1,12 @@
int foo(int a,int b){ return a+b; }

int main(){
if(true) {
using FuncPtr_5 = int (*)(int, int);
FuncPtr_5 add = foo;
using FuncPtr_7 = int (*)(int, int);
FuncPtr_7 add1 = foo;
}

}

18 changes: 18 additions & 0 deletions tests/CXXDefaultInitExprTest.cpp
@@ -0,0 +1,18 @@
template<typename T, bool array>
class Alloc
{
const int z;
T* data{nullptr};
const bool x{false};

public:
Alloc() : z{2}
{
}
};

int main()
{
Alloc<int, false> a;
Alloc<char, true> b;
}
64 changes: 64 additions & 0 deletions tests/CXXDefaultInitExprTest.expect
@@ -0,0 +1,64 @@
template<typename T, bool array>
class Alloc
{
const int z;
T* data{nullptr};
const bool x{false};

public:
Alloc() : z{2}
{
}
};
/* First instantiated from: CXXDefaultInitExprTest.cpp:16 */
#ifdef INSIGHTS_USE_TEMPLATE
class Alloc<int, 0>
{
const int z;
int * data;
const bool x;

public:
inline Alloc()
: z{2}
, data{nullptr}
, x{false}
{
}

inline constexpr Alloc(const Alloc<int, 0> &) = default;
inline constexpr Alloc(Alloc<int, 0> &&) = default;

};

#endif

/* First instantiated from: CXXDefaultInitExprTest.cpp:17 */
#ifdef INSIGHTS_USE_TEMPLATE
class Alloc<char, 1>
{
const int z;
char * data;
const bool x;

public:
inline Alloc()
: z{2}
, data{nullptr}
, x{false}
{
}

inline constexpr Alloc(const Alloc<char, 1> &) = default;
inline constexpr Alloc(Alloc<char, 1> &&) = default;

};

#endif


int main()
{
Alloc<int, false> a;
Alloc<char, true> b;
}
31 changes: 31 additions & 0 deletions tests/CXXDestructorTest.cpp
@@ -0,0 +1,31 @@
template<typename T, bool array>
class Alloc
{
T* data;

public:
Alloc() {
if( array ) {
data = new T[10];
data = new T[10]{1,2,3};
} else {
data = new T;
data = new T(2);
data = new T{2};
}
}

~Alloc() {
if( array ) {
delete[] data;
} else {
delete data;
}
}
};

int main()
{
Alloc<int, false> a;
Alloc<char, true> b;
}

0 comments on commit 86d8bd9

Please sign in to comment.