OSDN Git Service

PR c++/41468
[pf3gnuchains/gcc-fork.git] / gcc / cp / g++spec.c
index fbbe599..2853088 100644 (file)
@@ -1,25 +1,27 @@
-/* Specific flags and argument handling of the C++ front-end.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Specific flags and argument handling of the C++ front end.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2007, 2008, 2009 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "gcc.h"
 
 /* This bit is set if we saw a `-xfoo' language specification.  */
@@ -28,34 +30,46 @@ Boston, MA 02111-1307, USA.  */
 #define MATHLIB                (1<<2)
 /* This bit is set if they did `-lc'.  */
 #define WITHLIBC       (1<<3)
+/* Skip this option.  */
+#define SKIPOPT                (1<<4)
 
 #ifndef MATH_LIBRARY
 #define MATH_LIBRARY "-lm"
 #endif
+#ifndef MATH_LIBRARY_PROFILE
+#define MATH_LIBRARY_PROFILE MATH_LIBRARY
+#endif
 
 #ifndef LIBSTDCXX
 #define LIBSTDCXX "-lstdc++"
 #endif
+#ifndef LIBSTDCXX_PROFILE
+#define LIBSTDCXX_PROFILE LIBSTDCXX
+#endif
+#ifndef LIBSTDCXX_STATIC
+#define LIBSTDCXX_STATIC NULL
+#endif
 
 void
-lang_specific_driver (in_argc, in_argv, in_added_libraries)
-     int *in_argc;
-     const char *const **in_argv;
-     int *in_added_libraries;
+lang_specific_driver (int *in_argc, const char *const **in_argv,
+                     int *in_added_libraries)
 {
   int i, j;
 
-  /* If non-zero, the user gave us the `-v' flag.  */ 
-  int saw_verbose_flag = 0;
+  /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
+  int saw_profile_flag = 0;
 
-  /* This will be 0 if we encounter a situation where we should not
-     link in libstdc++.  */
-  int library = 1;
+  /* What do with libstdc++:
+     -1 means we should not link in libstdc++
+     0  means we should link in libstdc++ if it is needed
+     1  means libstdc++ is needed and should be linked in.
+     2  means libstdc++ is needed and should be linked statically.  */
+  int library = 0;
 
   /* The number of arguments being added to what's in argv, other than
      libraries.  We use this to track the number of times we've inserted
      -xc++/-xnone.  */
-  int added = 2;
+  int added = 0;
 
   /* Used to track options that take arguments, so we don't go wrapping
      those with -xc++/-xnone.  */
@@ -64,7 +78,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
   /* The new argument list will be contained in this.  */
   const char **arglist;
 
-  /* Non-zero if we saw a `-xfoo' language specification on the
+  /* Nonzero if we saw a `-xfoo' language specification on the
      command line.  Used to avoid adding our own -xc++ if the user
      already gave a language for the file.  */
   int saw_speclang = 0;
@@ -82,6 +96,9 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
   /* By default, we throw on the math library if we have one.  */
   int need_math = (MATH_LIBRARY[0] != '\0');
 
+  /* True if we saw -static.  */
+  int static_link = 0;
+
   /* True if we should add -shared-libgcc to the command-line.  */
   int shared_libgcc = 1;
 
@@ -101,7 +118,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
   argv = *in_argv;
   added_libraries = *in_added_libraries;
 
-  args = (int *) xcalloc (argc, sizeof (int));
+  args = XCNEWVEC (int, argc);
 
   for (i = 1; i < argc; i++)
     {
@@ -119,61 +136,89 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
 
       if (argv[i][0] == '-')
        {
-         if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
-                              || strcmp (argv[i], "-nodefaultlibs") == 0))
+         if (strcmp (argv[i], "-nostdlib") == 0
+             || strcmp (argv[i], "-nodefaultlibs") == 0)
            {
-             library = 0;
+             library = -1;
            }
-         else if (strcmp (argv[i], "-lm") == 0
-                  || strcmp (argv[i], "-lmath") == 0
-                  || strcmp (argv[i], MATH_LIBRARY) == 0
-#ifdef ALT_LIBM
-                  || strcmp (argv[i], ALT_LIBM) == 0
-#endif
-                 )
+         else if (strcmp (argv[i], MATH_LIBRARY) == 0)
            {
              args[i] |= MATHLIB;
              need_math = 0;
            }
          else if (strcmp (argv[i], "-lc") == 0)
            args[i] |= WITHLIBC;
-         else if (strcmp (argv[i], "-v") == 0)
+         else if (strcmp (argv[i], "-pg") == 0 || strcmp (argv[i], "-p") == 0)
+           saw_profile_flag++;
+         else if (strncmp (argv[i], "-x", 2) == 0)
            {
-             saw_verbose_flag = 1;
-             if (argc == 2)
-               {
-                 /* If they only gave us `-v', don't try to link
-                    in libg++.  */ 
-                 library = 0;
-               }
+             const char * arg;
+             if (argv[i][2] != '\0')
+               arg = argv[i]+2;
+             else if ((argv[i+1]) != NULL)
+               /* We need to swallow arg on next loop.  */
+               quote = arg = argv[i+1];
+             else  /* Error condition, message will be printed later.  */
+               arg = "";
+             if (library == 0
+                 && (strcmp (arg, "c++") == 0
+                     || strcmp (arg, "c++-cpp-output") == 0
+                     || strcmp (arg, "objective-c++") == 0
+                     || strcmp (arg, "objective-c++-cpp-output") == 0))
+               library = 1;
+               
+             saw_speclang = 1;
            }
-         else if (strncmp (argv[i], "-x", 2) == 0)
-           saw_speclang = 1;
+         else if (strcmp (argv[i], "-ObjC++") == 0)
+           {
+             if (library == 0)
+               library = 1;
+             saw_speclang = 1;
+           }
+         /* Arguments that go directly to the linker might be .o files,
+            or something, and so might cause libstdc++ to be needed.  */
+         else if (strcmp (argv[i], "-Xlinker") == 0)
+           {
+             quote = argv[i];
+             if (library == 0)
+               library = 1;
+           }
+         else if (strncmp (argv[i], "-Wl,", 4) == 0)
+           library = (library == 0) ? 1 : library;
+         /* Unrecognized libraries (e.g. -lfoo) may require libstdc++.  */
+         else if (strncmp (argv[i], "-l", 2) == 0)
+           library = (library == 0) ? 1 : library;
          else if (((argv[i][2] == '\0'
-                    && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
-                   || strcmp (argv[i], "-Xlinker") == 0
+                    && strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
                    || strcmp (argv[i], "-Tdata") == 0))
            quote = argv[i];
-         else if (library != 0 && ((argv[i][2] == '\0'
-                    && (char *) strchr ("cSEM", argv[i][1]) != NULL)
-                   || strcmp (argv[i], "-MM") == 0
-                   || strcmp (argv[i], "-fsyntax-only") == 0))
+         else if ((argv[i][2] == '\0'
+                   && strchr ("cSEM", argv[i][1]) != NULL)
+                  || strcmp (argv[i], "-MM") == 0
+                  || strcmp (argv[i], "-fsyntax-only") == 0)
            {
              /* Don't specify libraries if we won't link, since that would
                 cause a warning.  */
-             library = 0;
-             added -= 2;
+             library = -1;
            }
-         else if (strcmp (argv[i], "-static-libgcc") == 0 
-                  || strcmp (argv[i], "-static") == 0)
+         else if (strcmp (argv[i], "-static") == 0)
+           static_link = 1;
+         else if (strcmp (argv[i], "-static-libgcc") == 0)
            shared_libgcc = 0;
+         else if (strcmp (argv[i], "-static-libstdc++") == 0)
+           {
+             library = library >= 0 ? 2 : library;
+             args[i] |= SKIPOPT;
+           }
+         else if (DEFAULT_WORD_SWITCH_TAKES_ARG (&argv[i][1]))
+           i++;
          else
            /* Pass other options through.  */
            continue;
        }
       else
        {
-         int len; 
+         int len;
 
          if (saw_speclang)
            {
@@ -181,28 +226,39 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
              continue;
            }
 
-         /* If the filename ends in .c or .i, put options around it.
+         /* If the filename ends in .[chi], put options around it.
             But not if a specified -x option is currently active.  */
          len = strlen (argv[i]);
          if (len > 2
-             && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
+             && (argv[i][len - 1] == 'c'
+                 || argv[i][len - 1] == 'i'
+                 || argv[i][len - 1] == 'h')
              && argv[i][len - 2] == '.')
            {
              args[i] |= LANGSPEC;
              added += 2;
            }
+
+         /* If we don't know that this is a header file, we might
+            need to be linking in the libraries.  */
+         if (library == 0)
+           {
+             if ((len <= 2 || strcmp (argv[i] + (len - 2), ".H") != 0)
+                 && (len <= 2 || strcmp (argv[i] + (len - 2), ".h") != 0)
+                 && (len <= 4 || strcmp (argv[i] + (len - 4), ".hpp") != 0)
+                 && (len <= 3 || strcmp (argv[i] + (len - 3), ".hp") != 0)
+                 && (len <= 4 || strcmp (argv[i] + (len - 4), ".hxx") != 0)
+                 && (len <= 4 || strcmp (argv[i] + (len - 4), ".h++") != 0)
+                 && (len <= 4 || strcmp (argv[i] + (len - 4), ".HPP") != 0)
+                 && (len <= 4 || strcmp (argv[i] + (len - 4), ".tcc") != 0)
+                 && (len <= 3 || strcmp (argv[i] + (len - 3), ".hh") != 0))
+               library = 1;
+           }
        }
     }
 
   if (quote)
-    fatal ("argument to `%s' missing\n", quote);
-
-  /* If we know we don't have to do anything, bail now.  */
-  if (! added && ! library)
-    {
-      free (args);
-      return;
-    }
+    fatal ("argument to '%s' missing\n", quote);
 
   /* There's no point adding -shared-libgcc if we don't have a shared
      libgcc.  */
@@ -210,13 +266,14 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
   shared_libgcc = 0;
 #endif
 
-  /* Make sure to have room for the trailing NULL argument.  */
-  num_args = argc + added + need_math + shared_libgcc + 1;
-  arglist = (const char **) xmalloc (num_args * sizeof (char *));
+  /* Make sure to have room for the trailing NULL argument.
+     Add one for shared_libgcc or extra static library.  */
+  num_args = argc + added + need_math + (library > 0) * 4 + 2;
+  arglist = XNEWVEC (const char *, num_args);
 
   i = 0;
   j = 0;
-  
+
   /* Copy the 0th argument, i.e., the name of the program itself.  */
   arglist[i++] = argv[j++];
 
@@ -227,51 +284,90 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
 
       /* Make sure -lstdc++ is before the math library, since libstdc++
         itself uses those math routines.  */
-      if (!saw_math && (args[i] & MATHLIB) && library)
+      if (!saw_math && (args[i] & MATHLIB) && library > 0)
        {
          --j;
          saw_math = argv[i];
        }
 
-      if (!saw_libc && (args[i] & WITHLIBC) && library)
+      if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
        {
          --j;
          saw_libc = argv[i];
        }
 
-      /* Wrap foo.c and foo.i files in a language specification to
+      /* Wrap foo.[chi] files in a language specification to
         force the gcc compiler driver to run cc1plus on them.  */
       if (args[i] & LANGSPEC)
        {
          int len = strlen (argv[i]);
-         if (argv[i][len - 1] == 'i')
-           arglist[j++] = "-xc++-cpp-output";
-         else
-           arglist[j++] = "-xc++";
+         switch (argv[i][len - 1])
+           {
+           case 'c':
+             arglist[j++] = "-xc++";
+             break;
+           case 'i':
+             arglist[j++] = "-xc++-cpp-output";
+             break;
+           case 'h':
+             arglist[j++] = "-xc++-header";
+             break;
+           default:
+             gcc_unreachable ();
+           }
          arglist[j++] = argv[i];
          arglist[j] = "-xnone";
        }
 
+      if ((args[i] & SKIPOPT) != 0)
+       --j;
+
       i++;
       j++;
     }
 
   /* Add `-lstdc++' if we haven't already done so.  */
-  if (library)
+  if (library > 0)
     {
-      arglist[j++] = LIBSTDCXX;
-      added_libraries++;
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (library > 1 && !static_link)
+       {
+         arglist[j] = "-Wl,-Bstatic";
+         j++;
+       }
+#endif
+      arglist[j] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX;
+      if (arglist[j][0] != '-' || arglist[j][1] == 'l')
+       added_libraries++;
+      j++;
+      /* Add target-dependent static library, if necessary.  */
+      if ((static_link || library > 1) && LIBSTDCXX_STATIC != NULL)
+       {
+         arglist[j] = LIBSTDCXX_STATIC;
+         if (arglist[j][0] != '-' || arglist[j][1] == 'l')
+           added_libraries++;
+         j++;
+       }
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (library > 1 && !static_link)
+       {
+         arglist[j] = "-Wl,-Bdynamic";
+         j++;
+       }
+#endif
     }
   if (saw_math)
     arglist[j++] = saw_math;
-  else if (library && need_math)
+  else if (library > 0 && need_math)
     {
-      arglist[j++] = MATH_LIBRARY;
-      added_libraries++;
+      arglist[j] = saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY;
+      if (arglist[j][0] != '-' || arglist[j][1] == 'l')
+       added_libraries++;
+      j++;
     }
   if (saw_libc)
     arglist[j++] = saw_libc;
-  if (shared_libgcc)
+  if (shared_libgcc && !static_link)
     arglist[j++] = "-shared-libgcc";
 
   arglist[j] = NULL;
@@ -281,11 +377,11 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
   *in_added_libraries = added_libraries;
 }
 
-/* Called before linking.  Returns 0 on success and -1 on failure. */
-int lang_specific_pre_link ()  /* Not used for C++. */
+/* Called before linking.  Returns 0 on success and -1 on failure.  */
+int lang_specific_pre_link (void)  /* Not used for C++.  */
 {
   return 0;
 }
 
-/* Number of extra output files that lang_specific_pre_link may generate. */
-int lang_specific_extra_outfiles = 0;  /* Not used for C++. */
+/* Number of extra output files that lang_specific_pre_link may generate.  */
+int lang_specific_extra_outfiles = 0;  /* Not used for C++.  */