Skip to content

Commit

Permalink
[clang][Interp] Check for non-primitive types in unary operators
Browse files Browse the repository at this point in the history
For invalid cases (non-vector/complex/...), this should only happen
in error cases such as the attached test case.
  • Loading branch information
tbaederr committed Jul 14, 2024
1 parent 9d88990 commit 181e4c6
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
20 changes: 20 additions & 0 deletions clang/lib/AST/Interp/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4706,6 +4706,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
case UO_PostInc: { // x++
if (!Ctx.getLangOpts().CPlusPlus14)
return this->emitInvalid(E);
if (!T)
return this->emitError(E);

if (!this->visit(SubExpr))
return false;
Expand All @@ -4727,6 +4729,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
case UO_PostDec: { // x--
if (!Ctx.getLangOpts().CPlusPlus14)
return this->emitInvalid(E);
if (!T)
return this->emitError(E);

if (!this->visit(SubExpr))
return false;
Expand All @@ -4748,6 +4752,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
case UO_PreInc: { // ++x
if (!Ctx.getLangOpts().CPlusPlus14)
return this->emitInvalid(E);
if (!T)
return this->emitError(E);

if (!this->visit(SubExpr))
return false;
Expand Down Expand Up @@ -4795,6 +4801,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
case UO_PreDec: { // --x
if (!Ctx.getLangOpts().CPlusPlus14)
return this->emitInvalid(E);
if (!T)
return this->emitError(E);

if (!this->visit(SubExpr))
return false;
Expand Down Expand Up @@ -4840,6 +4848,9 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return E->isGLValue() || this->emitLoadPop(*T, E);
}
case UO_LNot: // !x
if (!T)
return this->emitError(E);

if (DiscardResult)
return this->discard(SubExpr);

Expand All @@ -4853,10 +4864,16 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return this->emitCast(PT_Bool, ET, E);
return true;
case UO_Minus: // -x
if (!T)
return this->emitError(E);

if (!this->visit(SubExpr))
return false;
return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
case UO_Plus: // +x
if (!T)
return this->emitError(E);

if (!this->visit(SubExpr)) // noop
return false;
return DiscardResult ? this->emitPop(*T, E) : true;
Expand All @@ -4873,6 +4890,9 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return this->discard(SubExpr);
return this->visit(SubExpr);
case UO_Not: // ~x
if (!T)
return this->emitError(E);

if (!this->visit(SubExpr))
return false;
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
Expand Down
10 changes: 10 additions & 0 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1290,3 +1290,13 @@ namespace NTTP {
return size(Chars);
}
}

#if __cplusplus >= 201402L
namespace UnaryOpError {
constexpr int foo() {
int f = 0;
++g; // both-error {{use of undeclared identifier 'g'}}
return f;
}
}
#endif

0 comments on commit 181e4c6

Please sign in to comment.