diff --git a/src/macro/Directives.cc b/src/macro/Directives.cc
index 64fa4854b343829364113708c1a25983d67e5005..d12a0f297cb90bccffa41032847e2a01fff6a1b0 100644
--- a/src/macro/Directives.cc
+++ b/src/macro/Directives.cc
@@ -245,19 +245,35 @@ For::interpret(ostream &output, vector<filesystem::path> &paths)
 void
 If::interpret(ostream &output, vector<filesystem::path> &paths)
 {
+  bool first_clause = true;
   for (const auto & [expr, body] : expr_and_body)
     try
       {
-        auto tmp = expr->eval();
-        RealPtr dp = dynamic_pointer_cast<Real>(tmp);
-        BoolPtr bp = dynamic_pointer_cast<Bool>(tmp);
-        if (!bp && !dp)
-          error(StackTrace("@#if",
-                           "The condition must evaluate to a boolean or a double", location));
-        if ((bp && *bp) || (dp && *dp))
+        if ((ifdef || ifndef) && first_clause)
           {
-            interpretBody(body, output, paths);
-            break;
+            first_clause = false;
+            VariablePtr vp = dynamic_pointer_cast<Variable>(expr);
+            assert(vp);
+            if ((ifdef && env.isVariableDefined(vp->getName()))
+                || (ifndef && !env.isVariableDefined(vp->getName())))
+              {
+                interpretBody(body, output, paths);
+                break;
+              }
+          }
+        else
+          {
+            auto tmp = expr->eval();
+            RealPtr dp = dynamic_pointer_cast<Real>(tmp);
+            BoolPtr bp = dynamic_pointer_cast<Bool>(tmp);
+            if (!bp && !dp)
+              error(StackTrace("@#if",
+                               "The condition must evaluate to a boolean or a double", location));
+            if ((bp && *bp) || (dp && *dp))
+              {
+                interpretBody(body, output, paths);
+                break;
+              }
           }
       }
     catch (StackTrace &ex)
@@ -286,31 +302,3 @@ If::interpretBody(const vector<DirectivePtr> &body, ostream &output, vector<file
       statement->interpret(output, paths);
     }
 }
-
-void
-Ifdef::interpret(ostream &output, vector<filesystem::path> &paths)
-{
-  for (const auto & [expr, body] : expr_and_body)
-    if (VariablePtr vp = dynamic_pointer_cast<Variable>(expr);
-        dynamic_pointer_cast<BaseType>(expr)
-        || (vp && env.isVariableDefined(vp->getName())))
-      {
-        interpretBody(body, output, paths);
-        break;
-      }
-  printEndLineInfo(output);
-}
-
-void
-Ifndef::interpret(ostream &output, vector<filesystem::path> &paths)
-{
-  for (const auto & [expr, body] : expr_and_body)
-    if (VariablePtr vp = dynamic_pointer_cast<Variable>(expr);
-        dynamic_pointer_cast<BaseType>(expr)
-        || (vp && !env.isVariableDefined(vp->getName())))
-      {
-        interpretBody(body, output, paths);
-        break;
-      }
-  printEndLineInfo(output);
-}
diff --git a/src/macro/Directives.hh b/src/macro/Directives.hh
index db71ae3f595ccbd87554b0c558c327d1c2ad143e..cc7ec6e1293d9ad0a4270a807344de0a110da7b2 100644
--- a/src/macro/Directives.hh
+++ b/src/macro/Directives.hh
@@ -175,24 +175,25 @@ namespace macro
      * If there is an `else` statement it is the last element in the vector. Its condition is true.
      */
     const vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body;
+    const bool ifdef, ifndef;
   public:
     If(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
-       Environment &env_arg, Tokenizer::location location_arg) :
-      Directive(env_arg, move(location_arg)), expr_and_body{move(expr_and_body_arg)} { }
+       Environment &env_arg, Tokenizer::location location_arg,
+       bool ifdef_arg = false, bool ifndef_arg = false) :
+      Directive(env_arg, move(location_arg)), expr_and_body{move(expr_and_body_arg)},
+      ifdef{ifdef_arg}, ifndef{ifndef_arg} { }
     void interpret(ostream &output, vector<filesystem::path> &paths) override;
   protected:
     void interpretBody(const vector<DirectivePtr> &body, ostream &output,
                        vector<filesystem::path> &paths);
   };
 
-
   class Ifdef : public If
   {
   public:
     Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
           Environment &env_arg, Tokenizer::location location_arg) :
-      If(move(expr_and_body_arg), env_arg, move(location_arg)) { }
-    void interpret(ostream &output, vector<filesystem::path> &paths) override;
+      If(move(expr_and_body_arg), env_arg, move(location_arg), true, false) { }
   };
 
 
@@ -201,8 +202,7 @@ namespace macro
   public:
     Ifndef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg,
            Environment &env_arg, Tokenizer::location location_arg) :
-      If(move(expr_and_body_arg), env_arg, move(location_arg)) { }
-    void interpret(ostream &output, vector<filesystem::path> &paths) override;
+      If(move(expr_and_body_arg), env_arg, move(location_arg), false, true) { }
   };
 }
 #endif