Skip to content

Commit

Permalink
Fixed #264: Wrap BinaryOperators in their according parentheses.
Browse files Browse the repository at this point in the history
This goes not only for `BinaryOperators`in fold expressions. All
expressions with a `BinaryOperator` are now wrapped.

While processing #264 there was another error with the `TypePrinter`
regarding the lambdas `auto` parameter which is fixed by this patch
as well.
  • Loading branch information
andreasfertig committed Oct 27, 2019
1 parent afb2d45 commit bb123e0
Show file tree
Hide file tree
Showing 20 changed files with 384 additions and 38 deletions.
12 changes: 5 additions & 7 deletions CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,15 +568,13 @@ void CodeGenerator::InsertArg(const BinaryOperator* stmt)
{
LAMBDA_SCOPE_HELPER(BinaryOperator);

InsertArg(stmt->getLHS());
mOutputFormatHelper.Append(" ", stmt->getOpcodeStr(), " ");
const bool needLHSParens{isa<BinaryOperator>(stmt->getLHS()->IgnoreImpCasts())};
WrapInParensIfNeeded(needLHSParens, [&] { InsertArg(stmt->getLHS()); });

// For + and - add the parentheses, if not already supplied. It looks like fold-expression to not carry them.
const bool needParens{
isa<BinaryOperator>(stmt->getRHS()->IgnoreImpCasts()) &&
((BinaryOperatorKind::BO_Add == stmt->getOpcode()) || (BinaryOperatorKind::BO_Sub == stmt->getOpcode()))};
mOutputFormatHelper.Append(" ", stmt->getOpcodeStr(), " ");

WrapInParensIfNeeded(needParens, [&] { InsertArg(stmt->getRHS()); });
const bool needRHSParens{isa<BinaryOperator>(stmt->getRHS()->IgnoreImpCasts())};
WrapInParensIfNeeded(needRHSParens, [&] { InsertArg(stmt->getRHS()); });
}
//-----------------------------------------------------------------------------

Expand Down
15 changes: 15 additions & 0 deletions InsightsHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,20 @@ class SimpleTypePrinter
return ret;
}

bool HandleType(const PackExpansionType* type)
{
type->dump();
const auto qt = type->getPattern();

const bool ret = HandleType(qt.getTypePtrOrNull());

if(ret) {
mData.Append("...");
}

return ret;
}

bool HandleType(const Type* type)
{
#define HANDLE_TYPE(t) \
Expand Down Expand Up @@ -533,6 +547,7 @@ class SimpleTypePrinter
HANDLE_TYPE(ConstantArrayType);
HANDLE_TYPE(InjectedClassNameType);
HANDLE_TYPE(DependentTemplateSpecializationType);
HANDLE_TYPE(PackExpansionType);

#undef HANDLE_TYPE
return false;
Expand Down
8 changes: 4 additions & 4 deletions tests/CXXFoldExprTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CXXFoldExprTest
template<>
inline int UnaryRightFold<int, int, int, int>(const int & __ts0, const int & __ts1, const int & __ts2, const int & __ts3)
{
return __ts0 / __ts1 / __ts2 / __ts3;
return __ts0 / (__ts1 / (__ts2 / __ts3));
}
#endif

Expand All @@ -27,7 +27,7 @@ class CXXFoldExprTest
template<>
inline int UnaryLeftFold<int, int, int, int>(const int & __ts0, const int & __ts1, const int & __ts2, const int & __ts3)
{
return __ts0 / __ts1 / __ts2 / __ts3;
return ((__ts0 / __ts1) / __ts2) / __ts3;
}
#endif

Expand All @@ -41,7 +41,7 @@ class CXXFoldExprTest
template<>
inline int BinaryRightFold<int, int, int, int>(const int & __ts0, const int & __ts1, const int & __ts2, const int & __ts3)
{
return __ts0 / __ts1 / __ts2 / __ts3 / 2;
return __ts0 / (__ts1 / (__ts2 / (__ts3 / 2)));
}
#endif

Expand All @@ -55,7 +55,7 @@ class CXXFoldExprTest
template<>
inline int BinaryLeftFold<int, int, int, int>(const int & __ts0, const int & __ts1, const int & __ts2, const int & __ts3)
{
return 2 / __ts0 / __ts1 / __ts2 / __ts3;
return (((2 / __ts0) / __ts1) / __ts2) / __ts3;
}
#endif

Expand Down
6 changes: 3 additions & 3 deletions tests/ClassOperatorHandler5Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ std::basic_string<char> trim(const std::basic_string<char> & input)

std::string final = std::basic_string<char>(input);
int i = 0;
while(i < static_cast<int>(input.length()) && static_cast<int>(input.operator[](i)) <= static_cast<int>(' ')) {
while((i < static_cast<int>(input.length())) && (static_cast<int>(input.operator[](i)) <= static_cast<int>(' '))) {
i++;
}

Expand All @@ -20,8 +20,8 @@ std::basic_string<char> trim(const std::basic_string<char> & input)
final.operator=(input.substr(static_cast<unsigned long>(i), input.length() - static_cast<unsigned long>(i)));
}

i = static_cast<int>(final.length()) - 1;
while(i >= 0 && static_cast<int>(final.operator[](i)) <= static_cast<int>(' ')) {
i = (static_cast<int>(final.length()) - 1);
while((i >= 0) && (static_cast<int>(final.operator[](i)) <= static_cast<int>(' '))) {
i--;
}

Expand Down
6 changes: 3 additions & 3 deletions tests/ClassOperatorHandler9Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ MyVector<int> operator+(const MyVector<int> & a, const MyVector<int> & b)
vec_t result = MyVector<int>(a.size()) /* NRVO variable */;
for(std::size_t s = 0; s <= a.size(); ++s)
{
result.operator[](s) = a.operator[](s) + b.operator[](s);
result.operator[](s) = (a.operator[](s) + b.operator[](s));
}

return MyVector<int>(result);
Expand All @@ -103,7 +103,7 @@ MyVector<int> operator*<int>(const MyVector<int> & a, const MyVector<int> & b)
MyVector<int> result = MyVector<int>(a.size()) /* NRVO variable */;
for(std::size_t s = 0; s <= a.size(); ++s)
{
result.operator[](s) = a.operator[](s) + b.operator[](s);
result.operator[](s) = (a.operator[](s) + b.operator[](s));
}

return MyVector<int>(result);
Expand All @@ -116,7 +116,7 @@ MyVector<int> Foo(const MyVector<int> & a, const MyVector<int> & b)
vec_t result = MyVector<int>{a.size()} /* NRVO variable */;
for(std::size_t s = 0; s <= a.size(); ++s)
{
result.operator[](s) = a.operator[](s) + b.operator[](s);
result.operator[](s) = (a.operator[](s) + b.operator[](s));
}

return MyVector<int>(result);
Expand Down
2 changes: 1 addition & 1 deletion tests/ConstexprFunctionHandlerTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ int main()
int fact4 = factorial(fact);
float f = Get();
const float f2 = Get();
return static_cast<int>(static_cast<float>(fact + d) + factFloat + static_cast<float>(fact2) + static_cast<float>(fact3) + static_cast<float>(fact4));
return static_cast<int>(((((static_cast<float>(fact + d)) + factFloat) + static_cast<float>(fact2)) + static_cast<float>(fact3)) + static_cast<float>(fact4));
}

74 changes: 74 additions & 0 deletions tests/FoldExpressionTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// + - * / % ^ & | = < > << >> += -= *= /= %= ^= &= |= <<= >>= == != <= >= && || , .* ->*

// Tests for some of the 32 operators

template<typename... Args>
constexpr auto plus(Args... args) { return (... + args); }

template<typename... Args>
constexpr auto minus(Args... args) { return (... - args); }

template<typename... Args>
constexpr auto times(Args... args) { return (... * args); }

template<typename... Args>
constexpr auto div(Args... args) { return (... / args); }

template<typename... Args>
constexpr auto mod(Args... args) { return (... % args); }

template<typename... Args>
constexpr auto bitwiseXOr(Args... args) { return (... ^ args); }

template<typename... Args>
constexpr auto bitwiseAnd(Args... args) { return (... & args); }

template<typename... Args>
constexpr auto bitwiseOr(Args... args) { return (... | args); }


// =

template<typename... Args>
constexpr auto lt(Args... args) { return (... < args); }

template<typename... Args>
constexpr auto gt(Args... args) { return (... > args); }


template<typename... Args>
constexpr auto logicalAnd(Args... args) { return (... && args); }

template<typename... Args>
constexpr auto logicalOr(Args... args) { return (... ||args); }

template<typename... Args>
constexpr auto comma(Args... args) { return (... , args); }

int main()
{
static_assert(6 == plus(1,2,3));
static_assert(1 == minus(6,2,3));
static_assert(18 == times(3,2,3));
static_assert(3 == div(18,2,3));
static_assert(0 == mod(18,4,2));
static_assert(0b00'011 == bitwiseXOr(0b11'101, 0b11'010, 0b00'100));
static_assert(0b00'010 == bitwiseAnd(0b11'010, 0b11'010, 0b00'010));
static_assert(0b11'111 == bitwiseOr(0b11'001, 0b11'010, 0b00'100));

// =

static_assert(false == lt(1,2,0));
static_assert(false == gt(1,2,1));


static_assert(false == logicalAnd(true, true, true, false));
static_assert(true == logicalOr(true, true, true, false));

static_assert(4 == comma(1,2,3,4));

// Verify that we do not introduce parens here.
int x = 4;
x /= 2;
}

Loading

0 comments on commit bb123e0

Please sign in to comment.