Skip to content

Commit

Permalink
Fixed #131: Global DecompositionDecl transformation was wrong.
Browse files Browse the repository at this point in the history
A global DecompositionDecl which involves a callExpr introduces the
decomposed variables. With this, the global VarDecl matcher matched
multiple times which resulted in an messed up transformation. Added a
limit to the matcher to skip the decomposed variable declarations.
  • Loading branch information
Andreas Fertig committed Mar 1, 2019
1 parent 6c37c6a commit 4783d94
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 24 deletions.
7 changes: 7 additions & 0 deletions CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2705,6 +2705,13 @@ void CodeGenerator::WrapInCurlys(T&& lambda, const AddSpaceAtTheEnd addSpaceAtTh
void StructuredBindingsCodeGenerator::InsertArg(const DeclRefExpr* stmt)
{
const auto name = GetName(*stmt);

// Special case for structured bindings, probably only with std::tuple. The get which is used to retrieve the value
// seems to carry no std:: in front. Insert it to make the code compile.
if(not name.empty() && BeginsWith(name, "get")) {
mOutputFormatHelper.Append("std::");
}

mOutputFormatHelper.Append(name);

if(name.empty() || EndsWith(name, "::")) {
Expand Down
25 changes: 16 additions & 9 deletions GlobalVariableHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,28 @@ using namespace clang::ast_matchers;

namespace clang::ast_matchers {
const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl> varTemplateSpecDecl;
}
const internal::VariadicDynCastAllOfMatcher<Decl, DecompositionDecl> decompositionDecl;
} // namespace clang::ast_matchers

namespace clang::insights {

GlobalVariableHandler::GlobalVariableHandler(Rewriter& rewrite, MatchFinder& matcher)
: InsightsBase(rewrite)
{
matcher.addMatcher(varDecl(hasParent(translationUnitDecl()),
unless(anyOf(isExpansionInSystemHeader(),
isMacroOrInvalidLocation(),
hasDescendant(cxxRecordDecl(isLambda())),
varTemplateSpecDecl(),
isTemplate)))
.bind("varDecl"),
this);
matcher.addMatcher(
varDecl(hasParent(translationUnitDecl()),
unless(anyOf(
isExpansionInSystemHeader(),
isMacroOrInvalidLocation(),
hasDescendant(cxxRecordDecl(isLambda())),
varTemplateSpecDecl(),
// A DecompositionDecl in global scope is different in the AST than one in a function for example.
// Try to find out whether this VarDecl is the result of a DecompositionDecl, if so bail out.
hasInitializer(ignoringImpCasts(
callExpr(hasAnyArgument(ignoringParenImpCasts(declRefExpr(to(decompositionDecl()))))))),
isTemplate)))
.bind("varDecl"),
this);
}
//-----------------------------------------------------------------------------

Expand Down
10 changes: 10 additions & 0 deletions InsightsStrCat.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ static inline bool EndsWith(const std::string& src, const std::string& ending)
}
//-----------------------------------------------------------------------------

static inline bool BeginsWith(const std::string& src, const std::string& begining)
{
if(begining.size() > src.size()) {
return false;
}

return std::equal(begining.begin(), begining.end(), src.begin());
}
//-----------------------------------------------------------------------------

static inline std::string ToString(const llvm::APSInt& val)
{
return val.toString(10);
Expand Down
3 changes: 3 additions & 0 deletions tests/GlobalVarFromFunctionInitTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int Func() { return 2; }

int v = /* */ Func(); //
8 changes: 8 additions & 0 deletions tests/GlobalVarFromFunctionInitTest.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
int Func()
{
return 2;
}


int v = Func();
//
5 changes: 5 additions & 0 deletions tests/Issue131.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <tuple>

std::tuple<int, float> foo();

auto [a, b] = foo();
9 changes: 9 additions & 0 deletions tests/Issue131.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <tuple>

std::tuple<int, float> foo();


std::tuple<int, float> __foo5 = foo();
std::tuple_element<0, std::tuple<int, float> >::type& a = std::get<0ul>(__foo5);
std::tuple_element<1, std::tuple<int, float> >::type& b = std::get<1ul>(__foo5);

12 changes: 6 additions & 6 deletions tests/StructuredBindingsHandler6Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,12 @@ int main()
const char& a19 = __aa75[1];
std::tuple<int, char, double> muple = std::make_tuple(1, 'a', 2.2999999999999998);
std::tuple<int, char, double> & __muple80 = muple;
std::tuple_element<0, std::tuple<int, char, double> >::type& i = get<0ul>(__muple80);
std::tuple_element<1, std::tuple<int, char, double> >::type& c = get<1ul>(__muple80);
std::tuple_element<2, std::tuple<int, char, double> >::type& d = get<2ul>(__muple80);
std::tuple_element<0, std::tuple<int, char, double> >::type& i = std::get<0ul>(__muple80);
std::tuple_element<1, std::tuple<int, char, double> >::type& c = std::get<1ul>(__muple80);
std::tuple_element<2, std::tuple<int, char, double> >::type& d = std::get<2ul>(__muple80);
std::tuple<int, char, double> __muple82 = std::tuple<int, char, double>(muple);
std::tuple_element<0, std::tuple<int, char, double> >::type& ii = get<0ul>(__muple82);
std::tuple_element<1, std::tuple<int, char, double> >::type& cc = get<1ul>(__muple82);
std::tuple_element<2, std::tuple<int, char, double> >::type& dd = get<2ul>(__muple82);
std::tuple_element<0, std::tuple<int, char, double> >::type& ii = std::get<0ul>(__muple82);
std::tuple_element<1, std::tuple<int, char, double> >::type& cc = std::get<1ul>(__muple82);
std::tuple_element<2, std::tuple<int, char, double> >::type& dd = std::get<2ul>(__muple82);
}

18 changes: 18 additions & 0 deletions tests/StructuredBindingsHandler9Test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <tuple>

std::tuple<int, float> foo;

auto [a, b] = foo;
auto& [ra, rb] = foo;


char c[3]{};

auto [x, y, z] = c;

auto& [cx, cy, cz] = c;


std::tuple<int, float> Func();

const auto& [fa, fb] = Func();
38 changes: 38 additions & 0 deletions tests/StructuredBindingsHandler9Test.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <tuple>

std::tuple<int, float> foo = std::tuple<int, float>();


std::tuple<int, float> __foo5 = std::tuple<int, float>(foo);
std::tuple_element<0, std::tuple<int, float> >::type& a = std::get<0ul>(__foo5);
std::tuple_element<1, std::tuple<int, float> >::type& b = std::get<1ul>(__foo5);

std::tuple<int, float> & __foo6 = foo;
std::tuple_element<0, std::tuple<int, float> >::type& ra = std::get<0ul>(__foo6);
std::tuple_element<1, std::tuple<int, float> >::type& rb = std::get<1ul>(__foo6);



char c[3] = {'\0', '\0', '\0'};


char __c11[3] = {c[0], c[1], c[2]};
char x = __c11[0];
char y = __c11[1];
char z = __c11[2];


char (&__c13)[3] = c;
char& cx = __c13[0];
char& cy = __c13[1];
char& cz = __c13[2];



std::tuple<int, float> Func();


const std::tuple<int, float> & __Func18 = Func();
std::tuple_element<0, const std::tuple<int, float> >::type& fa = std::get<0ul>(__Func18);
std::tuple_element<1, const std::tuple<int, float> >::type& fb = std::get<1ul>(__Func18);

7 changes: 0 additions & 7 deletions tests/TupeInRangeBasedForTest.cerr

This file was deleted.

4 changes: 2 additions & 2 deletions tests/TupeInRangeBasedForTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ int main()
for( ; std::operator!=(__begin1, __end1); __begin1.operator++() )
{
std::tuple<std::basic_string<char>, int> __operator15 = std::tuple<std::basic_string<char>, int>(__begin1.operator*());
std::basic_string<char>& s = get<0ul>(__operator15);
std::tuple_element<1, std::tuple<std::basic_string<char>, int> >::type& n = get<1ul>(__operator15);
std::basic_string<char>& s = std::get<0ul>(__operator15);
std::tuple_element<1, std::tuple<std::basic_string<char>, int> >::type& n = std::get<1ul>(__operator15);
printf("c=%s, n=%d\n", s.c_str(), n);
}
}
Expand Down

0 comments on commit 4783d94

Please sign in to comment.