This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[libcpp PATCH] Resolve DR#412 - unevaluated #elif (PR preprocessor/60570)


As discussed in the PR, this patch partially reverts Tom's change
in r136209.  (The is_if argument to _cpp_parse_expr is kept for the
sake of diagnostics.)

The change made sense at that time, but now we have DR#412 resolved.
This DR deals with the case where we have an #elif conditional that
doesn't have to be evaluated:

#if 1
int i;
#elif 1/0
#endif

and this DR says that such #elifs should be skipped.
This change is deliberately not conditioned on any standard version.

Jason, Joseph, does it make sense to put this into GCC 5, or should it wait
for GCC 6?  Since this change makes the preprocessor more permissive, it
should hurt nobody.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2015-01-22  Marek Polacek  <polacek@redhat.com>

	DR#412
	PR preprocessor/60570
	* directives.c (do_elif): Don't evaluate #elif conditionals
	when they don't need to be.

	* gcc.dg/cpp/pr36320.c: Turn dg-error into dg-bogus.
	* gcc.dg/cpp/pr60570.c: New test.

diff --git gcc/gcc/testsuite/gcc.dg/cpp/pr36320.c gcc/gcc/testsuite/gcc.dg/cpp/pr36320.c
index d136a69..cc2baa7 100644
--- gcc/gcc/testsuite/gcc.dg/cpp/pr36320.c
+++ gcc/gcc/testsuite/gcc.dg/cpp/pr36320.c
@@ -1,8 +1,8 @@
 /* PR 36320 - #elif still requires valid expression.  */
-
+/* DR#412: #elif doesn't have to be valid expression (PR60570).  */
 /* { dg-do preprocess } */
 
 int z;
 #if 1
-#elif   /* { dg-error "with no expression" } */
+#elif	/* { dg-bogus "with no expression" } */
 #endif
diff --git gcc/gcc/testsuite/gcc.dg/cpp/pr60570.c gcc/gcc/testsuite/gcc.dg/cpp/pr60570.c
index e69de29..4755206 100644
--- gcc/gcc/testsuite/gcc.dg/cpp/pr60570.c
+++ gcc/gcc/testsuite/gcc.dg/cpp/pr60570.c
@@ -0,0 +1,48 @@
+/* PR preprocessor/60570 */
+/* { dg-do preprocess } */
+
+#if 1
+int i;
+#elif 1/0
+#endif
+
+#if 1
+int j;
+#elif
+#endif
+
+#if 0
+#elif 1/0	/* { dg-error "division by zero" } */
+int k;
+#endif
+
+#if 0
+#elif		/* { dg-error "with no expression" } */
+int n;
+#endif
+
+#if 1
+# if 1
+int l;
+# elif 1/0
+# endif
+#endif
+
+#if 1
+# if 1
+int l;
+# elif
+# endif
+#endif
+
+#if 1
+# if 0
+# elif 1/0	/* { dg-error "division by zero" } */
+# endif
+#endif
+
+#if 1
+# if 0
+# elif		/* { dg-error "with no expression" } */
+# endif
+#endif
diff --git gcc/libcpp/directives.c gcc/libcpp/directives.c
index ab4f15c..37cd109 100644
--- gcc/libcpp/directives.c
+++ gcc/libcpp/directives.c
@@ -2036,23 +2036,16 @@ do_elif (cpp_reader *pfile)
 	}
       ifs->type = T_ELIF;
 
-      if (! ifs->was_skipping)
+      /* See DR#412: "Only the first group whose control condition
+	 evaluates to true (nonzero) is processed; any following groups
+	 are skipped and their controlling directives are processed as
+	 if they were in a group that is skipped."  */
+      if (ifs->skip_elses)
+	pfile->state.skipping = 1;
+      else
 	{
-	  bool value;
-	  /* The standard mandates that the expression be parsed even
-	     if we are skipping elses at this point -- the lexical
-	     restrictions on #elif only apply to skipped groups, but
-	     this group is not being skipped.  Temporarily set
-	     skipping to false to get lexer warnings.  */
-	  pfile->state.skipping = 0;
-	  value = _cpp_parse_expr (pfile, false);
-	  if (ifs->skip_elses)
-	    pfile->state.skipping = 1;
-	  else
-	    {
-	      pfile->state.skipping = ! value;
-	      ifs->skip_elses = value;
-	    }
+	  pfile->state.skipping = ! _cpp_parse_expr (pfile, false);
+	  ifs->skip_elses = ! pfile->state.skipping;
 	}
 
       /* Invalidate any controlling macro.  */

	Marek


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]