diff --git a/lib/Differentiator/CladUtils.cpp b/lib/Differentiator/CladUtils.cpp index 832dc93d9..16fc56ea0 100644 --- a/lib/Differentiator/CladUtils.cpp +++ b/lib/Differentiator/CladUtils.cpp @@ -576,6 +576,14 @@ namespace clad { auto opCode = UnOp->getOpcode(); if (opCode == clang::UO_PreInc || opCode == clang::UO_PreDec) Visit(UnOp->getSubExpr()); + else if (opCode == UnaryOperatorKind::UO_Real || + opCode == UnaryOperatorKind::UO_Imag) { + /// FIXME: Considering real/imaginary part atomic is + /// not always correct since the subexpression can + /// be more complex than just a DeclRefExpr. + /// (e.g. `__real (n++ ? z1 : z2)`) + m_Exprs.push_back(UnOp); + } } void VisitDeclRefExpr(clang::DeclRefExpr* DRE) { diff --git a/lib/Differentiator/TBRAnalyzer.cpp b/lib/Differentiator/TBRAnalyzer.cpp index 86490d822..4bcaa85c7 100644 --- a/lib/Differentiator/TBRAnalyzer.cpp +++ b/lib/Differentiator/TBRAnalyzer.cpp @@ -736,6 +736,11 @@ bool TBRAnalyzer::VisitUnaryOperator(clang::UnaryOperator* UnOp) { markLocation(innerExpr); } } + /// FIXME: Ideally, `__real` and `__imag` operators should be + /// treated as member expressions. However, it is not clear + /// where the FieldDecls of real and imaginary parts should be + /// deduced from (their names might be compiler-specific). + /// So for now we visit the whole subexpression. return true; }