svn commit: r228366 - in vendor/clang/dist: bindings/python/clang bindings/python/tests/cindex include/clang/Basic include/clang/Driver include/clang/Frontend lib/Basic lib/CodeGen lib/Driver lib/F...

Dimitry Andric dim at FreeBSD.org
Fri Dec 9 18:30:43 UTC 2011


Author: dim
Date: Fri Dec  9 18:30:42 2011
New Revision: 228366
URL: http://svn.freebsd.org/changeset/base/228366

Log:
  Vendor import of clang 3.0 final release:
  http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_30/final@145349

Added:
  vendor/clang/dist/test/CodeGen/pr9614.c
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.0/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.1/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing3/lib/gcc/i386-unknown-linux/4.7.98/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing3/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/bin/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/bin/.keep
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.98/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99-rc5/
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99-rc5/crtbegin.o
  vendor/clang/dist/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99/crtbegin.o
Modified:
  vendor/clang/dist/bindings/python/clang/cindex.py
  vendor/clang/dist/bindings/python/tests/cindex/test_type.py
  vendor/clang/dist/include/clang/Basic/Builtins.def
  vendor/clang/dist/include/clang/Driver/CC1Options.td
  vendor/clang/dist/include/clang/Driver/ToolChain.h
  vendor/clang/dist/include/clang/Frontend/HeaderSearchOptions.h
  vendor/clang/dist/lib/Basic/Version.cpp
  vendor/clang/dist/lib/CodeGen/CGObjCGNU.cpp
  vendor/clang/dist/lib/CodeGen/CodeGenModule.cpp
  vendor/clang/dist/lib/CodeGen/CodeGenModule.h
  vendor/clang/dist/lib/Driver/CMakeLists.txt
  vendor/clang/dist/lib/Driver/ToolChain.cpp
  vendor/clang/dist/lib/Driver/ToolChains.cpp
  vendor/clang/dist/lib/Driver/ToolChains.h
  vendor/clang/dist/lib/Driver/Tools.cpp
  vendor/clang/dist/lib/Frontend/CompilerInvocation.cpp
  vendor/clang/dist/lib/Frontend/InitHeaderSearch.cpp
  vendor/clang/dist/test/Analysis/iterators.cpp
  vendor/clang/dist/test/Analysis/security-syntax-checks.m
  vendor/clang/dist/test/Driver/linux-ld.c
  vendor/clang/dist/test/PCH/reloc.c
  vendor/clang/dist/test/Preprocessor/header_lookup1.c
  vendor/clang/dist/test/lit.cfg

Modified: vendor/clang/dist/bindings/python/clang/cindex.py
==============================================================================
--- vendor/clang/dist/bindings/python/clang/cindex.py	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/bindings/python/clang/cindex.py	Fri Dec  9 18:30:42 2011	(r228366)
@@ -815,7 +815,7 @@ class Cursor(Structure):
     The Cursor class represents a reference to an element within the AST. It
     acts as a kind of iterator.
     """
-    _fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)]
+    _fields_ = [("_kind_id", c_int), ("xdata", c_int), ("data", c_void_p * 3)]
 
     def __eq__(self, other):
         return Cursor_eq(self, other)
@@ -1019,7 +1019,7 @@ TypeKind.OBJCINTERFACE = TypeKind(108)
 TypeKind.OBJCOBJECTPOINTER = TypeKind(109)
 TypeKind.FUNCTIONNOPROTO = TypeKind(110)
 TypeKind.FUNCTIONPROTO = TypeKind(111)
-
+TypeKind.CONSTANTARRAY = TypeKind(112)
 
 class Type(Structure):
     """

Modified: vendor/clang/dist/bindings/python/tests/cindex/test_type.py
==============================================================================
--- vendor/clang/dist/bindings/python/tests/cindex/test_type.py	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/bindings/python/tests/cindex/test_type.py	Fri Dec  9 18:30:42 2011	(r228366)
@@ -74,3 +74,22 @@ def test_a_struct():
 
     else:
         assert False, "Didn't find teststruct??"
+
+
+constarrayInput="""
+struct teststruct {
+  void *A[2];
+};
+"""
+def testConstantArray():
+    index = Index.create()
+    tu = index.parse('t.c', unsaved_files = [('t.c',constarrayInput)])
+
+    for n in tu.cursor.get_children():
+        if n.spelling == 'teststruct':
+            fields = list(n.get_children())
+            assert fields[0].spelling == 'A'
+            assert fields[0].type.kind == TypeKind.CONSTANTARRAY
+            break
+    else:
+        assert False, "Didn't find teststruct??"

Modified: vendor/clang/dist/include/clang/Basic/Builtins.def
==============================================================================
--- vendor/clang/dist/include/clang/Basic/Builtins.def	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/include/clang/Basic/Builtins.def	Fri Dec  9 18:30:42 2011	(r228366)
@@ -672,16 +672,16 @@ LIBBUILTIN(rindex, "c*cC*i",      "f",  
 LIBBUILTIN(bzero, "vv*z",         "f",     "strings.h", ALL_LANGUAGES)
 // POSIX unistd.h
 LIBBUILTIN(_exit, "vi",           "fr",    "unistd.h", ALL_LANGUAGES)
-LIBBUILTIN(vfork, "iJ",           "fj",    "unistd.h", ALL_LANGUAGES)
+LIBBUILTIN(vfork, "i",            "fj",    "unistd.h", ALL_LANGUAGES)
 // POSIX setjmp.h
 
 // In some systems setjmp is a macro that expands to _setjmp. We undefine
 // it here to avoid having two identical LIBBUILTIN entries.
 #undef setjmp
 LIBBUILTIN(_setjmp, "iJ",         "fj",   "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(__sigsetjmp, "iJ",     "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(__sigsetjmp, "iJi",    "fj",   "setjmp.h", ALL_LANGUAGES)
 LIBBUILTIN(setjmp, "iJ",          "fj",   "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(sigsetjmp, "iJ",       "fj",   "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(sigsetjmp, "iJi",      "fj",   "setjmp.h", ALL_LANGUAGES)
 LIBBUILTIN(setjmp_syscall, "iJ",  "fj",   "setjmp.h", ALL_LANGUAGES)
 LIBBUILTIN(savectx, "iJ",         "fj",   "setjmp.h", ALL_LANGUAGES)
 LIBBUILTIN(qsetjmp, "iJ",         "fj",   "setjmp.h", ALL_LANGUAGES)

Modified: vendor/clang/dist/include/clang/Driver/CC1Options.td
==============================================================================
--- vendor/clang/dist/include/clang/Driver/CC1Options.td	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/include/clang/Driver/CC1Options.td	Fri Dec  9 18:30:42 2011	(r228366)
@@ -642,6 +642,17 @@ def isystem : JoinedOrSeparate<"-isystem
 def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">,
   HelpText<"Add directory to SYSTEM include search path, "
            "absolute paths are relative to -isysroot">;
+def internal_isystem : JoinedOrSeparate<"-internal-isystem">,
+  MetaVarName<"<directory>">,
+  HelpText<"Add directory to the internal system include search path; these "
+           "are assumed to not be user-provided and are used to model system "
+           "and standard headers' paths.">;
+def internal_externc_isystem : JoinedOrSeparate<"-internal-externc-isystem">,
+  MetaVarName<"<directory>">,
+  HelpText<"Add directory to the internal system include search path with "
+           "implicit extern \"C\" semantics; these are assumed to not be "
+           "user-provided and are used to model system and standard headers' "
+           "paths.">;
 def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">,
   HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">;
 def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">,

Modified: vendor/clang/dist/include/clang/Driver/ToolChain.h
==============================================================================
--- vendor/clang/dist/include/clang/Driver/ToolChain.h	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/include/clang/Driver/ToolChain.h	Fri Dec  9 18:30:42 2011	(r228366)
@@ -195,15 +195,21 @@ public:
   /// FIXME: this really belongs on some sort of DeploymentTarget abstraction
   virtual bool hasBlocksRuntime() const { return true; }
 
+  /// \brief Add the clang cc1 arguments for system include paths.
+  ///
+  /// This routine is responsible for adding the necessary cc1 arguments to
+  /// include headers from standard system header directories.
+  virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+                                         ArgStringList &CC1Args) const;
+
   // GetCXXStdlibType - Determine the C++ standard library type to use with the
   // given compilation arguments.
   virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
 
   /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set
   /// the include paths to use for the given C++ standard library type.
-  virtual void AddClangCXXStdlibIncludeArgs(const ArgList &Args,
-                                            ArgStringList &CmdArgs,
-                                            bool ObjCXXAutoRefCount) const;
+  virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+                                            ArgStringList &CC1Args) const;
 
   /// AddCXXStdlibLibArgs - Add the system specific linker arguments to use
   /// for the given C++ standard library type.

Modified: vendor/clang/dist/include/clang/Frontend/HeaderSearchOptions.h
==============================================================================
--- vendor/clang/dist/include/clang/Frontend/HeaderSearchOptions.h	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/include/clang/Frontend/HeaderSearchOptions.h	Fri Dec  9 18:30:42 2011	(r228366)
@@ -49,10 +49,24 @@ public:
     /// path.
     unsigned IgnoreSysRoot : 1;
 
+    /// \brief True if this entry is an internal search path.
+    ///
+    /// This typically indicates that users didn't directly provide it, but
+    /// instead it was provided by a compatibility layer for a particular
+    /// system. This isn't redundant with IsUserSupplied (even though perhaps
+    /// it should be) because that is false for user provided '-iwithprefix'
+    /// header search entries.
+    unsigned IsInternal : 1;
+
+    /// \brief True if this entry's headers should be wrapped in extern "C".
+    unsigned ImplicitExternC : 1;
+
     Entry(StringRef path, frontend::IncludeDirGroup group,
-          bool isUserSupplied, bool isFramework, bool ignoreSysRoot)
+          bool isUserSupplied, bool isFramework, bool ignoreSysRoot,
+          bool isInternal, bool implicitExternC)
       : Path(path), Group(group), IsUserSupplied(isUserSupplied),
-        IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot) {}
+        IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot),
+        IsInternal(isInternal), ImplicitExternC(implicitExternC) {}
   };
 
   /// If non-empty, the directory to use as a "virtual system root" for include
@@ -98,9 +112,10 @@ public:
 
   /// AddPath - Add the \arg Path path to the specified \arg Group list.
   void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
-               bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot) {
+               bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot,
+               bool IsInternal = false, bool ImplicitExternC = false) {
     UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework,
-                                IgnoreSysRoot));
+                                IgnoreSysRoot, IsInternal, ImplicitExternC));
   }
 };
 

Modified: vendor/clang/dist/lib/Basic/Version.cpp
==============================================================================
--- vendor/clang/dist/lib/Basic/Version.cpp	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/lib/Basic/Version.cpp	Fri Dec  9 18:30:42 2011	(r228366)
@@ -32,7 +32,7 @@ std::string getClangRepositoryPath() {
 
   // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
   // pick up a tag in an SVN export, for example.
-  static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/branches/release_30/lib/Basic/Version.cpp $");
+  static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_30/final/lib/Basic/Version.cpp $");
   if (URL.empty()) {
     URL = SVNRepository.slice(SVNRepository.find(':'),
                               SVNRepository.find("/lib/Basic"));

Modified: vendor/clang/dist/lib/CodeGen/CGObjCGNU.cpp
==============================================================================
--- vendor/clang/dist/lib/CodeGen/CGObjCGNU.cpp	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/lib/CodeGen/CGObjCGNU.cpp	Fri Dec  9 18:30:42 2011	(r228366)
@@ -538,11 +538,12 @@ protected:
                                  llvm::Value *cmd,
                                  llvm::MDNode *node) {
     CGBuilderTy &Builder = CGF.Builder;
-    llvm::Value *imp = Builder.CreateCall2(MsgLookupFn, 
-            EnforceType(Builder, Receiver, IdTy),
-            EnforceType(Builder, cmd, SelectorTy));
-    cast<llvm::CallInst>(imp)->setMetadata(msgSendMDKind, node);
-    return imp;
+    llvm::Value *args[] = {
+      EnforceType(Builder, Receiver, IdTy),
+      EnforceType(Builder, cmd, SelectorTy) };
+    llvm::CallSite imp = CGF.EmitCallOrInvoke(MsgLookupFn, args);
+    imp->setMetadata(msgSendMDKind, node);
+    return imp.getInstruction();
   }
   virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
                                       llvm::Value *ObjCSuper,
@@ -597,16 +598,17 @@ class CGObjCGNUstep : public CGObjCGNU {
       // The lookup function is guaranteed not to capture the receiver pointer.
       LookupFn->setDoesNotCapture(1);
 
-      llvm::CallInst *slot =
-          Builder.CreateCall3(LookupFn,
-              EnforceType(Builder, ReceiverPtr, PtrToIdTy),
-              EnforceType(Builder, cmd, SelectorTy),
-              EnforceType(Builder, self, IdTy));
-      slot->setOnlyReadsMemory();
+      llvm::Value *args[] = {
+        EnforceType(Builder, ReceiverPtr, PtrToIdTy),
+        EnforceType(Builder, cmd, SelectorTy),
+        EnforceType(Builder, self, IdTy) };
+      llvm::CallSite slot = CGF.EmitCallOrInvoke(LookupFn, args);
+      slot.setOnlyReadsMemory();
       slot->setMetadata(msgSendMDKind, node);
 
       // Load the imp from the slot
-      llvm::Value *imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
+      llvm::Value *imp =
+        Builder.CreateLoad(Builder.CreateStructGEP(slot.getInstruction(), 4));
 
       // The lookup function may have changed the receiver, so make sure we use
       // the new one.
@@ -1361,8 +1363,8 @@ llvm::Constant *CGObjCGNU::GenerateClass
       LongTy,                 // abi_version
       IvarOffsets->getType(), // ivar_offsets
       Properties->getType(),  // properties
-      Int64Ty,                // strong_pointers
-      Int64Ty,                // weak_pointers
+      IntPtrTy,               // strong_pointers
+      IntPtrTy,               // weak_pointers
       NULL);
   llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
   // Fill in the structure
@@ -1723,12 +1725,14 @@ void CGObjCGNU::GenerateProtocolHolderCa
 /// bitfield / with the 63rd bit set will be 1<<64.
 llvm::Constant *CGObjCGNU::MakeBitField(llvm::SmallVectorImpl<bool> &bits) {
   int bitCount = bits.size();
-  if (bitCount < 64) {
+  int ptrBits =
+        (TheModule.getPointerSize() == llvm::Module::Pointer32) ? 32 : 64;
+  if (bitCount < ptrBits) {
     uint64_t val = 1;
     for (int i=0 ; i<bitCount ; ++i) {
       if (bits[i]) val |= 1ULL<<(i+1);
     }
-    return llvm::ConstantInt::get(Int64Ty, val);
+    return llvm::ConstantInt::get(IntPtrTy, val);
   }
   llvm::SmallVector<llvm::Constant*, 8> values;
   int v=0;
@@ -1748,8 +1752,6 @@ llvm::Constant *CGObjCGNU::MakeBitField(
   llvm::Constant *GS = MakeGlobal(llvm::StructType::get(Int32Ty, arrayTy,
         NULL), fields);
   llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
-  if (IntPtrTy != Int64Ty)
-    ptr = llvm::ConstantExpr::getZExt(ptr, Int64Ty);
   return ptr;
 }
 
@@ -2073,12 +2075,12 @@ void CGObjCGNU::GenerateClass(const ObjC
       }
       ++ivarIndex;
   }
-  llvm::Constant *Zero64 = llvm::ConstantInt::get(Int64Ty, 0);
+  llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
   //Generate metaclass for class methods
   llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
       NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList(
         empty, empty, empty), ClassMethodList, NULLPtr,
-      NULLPtr, NULLPtr, Zero64, Zero64, true);
+      NULLPtr, NULLPtr, ZeroPtr, ZeroPtr, true);
 
   // Generate the class structure
   llvm::Constant *ClassStruct =

Modified: vendor/clang/dist/lib/CodeGen/CodeGenModule.cpp
==============================================================================
--- vendor/clang/dist/lib/CodeGen/CodeGenModule.cpp	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/lib/CodeGen/CodeGenModule.cpp	Fri Dec  9 18:30:42 2011	(r228366)
@@ -29,6 +29,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Mangle.h"
 #include "clang/AST/RecordLayout.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
@@ -858,6 +859,59 @@ void CodeGenModule::EmitGlobal(GlobalDec
   }
 }
 
+namespace {
+  struct FunctionIsDirectlyRecursive :
+    public RecursiveASTVisitor<FunctionIsDirectlyRecursive> {
+    const StringRef Name;
+    bool Result;
+    FunctionIsDirectlyRecursive(const FunctionDecl *F) :
+      Name(F->getName()), Result(false) {
+    }
+    typedef RecursiveASTVisitor<FunctionIsDirectlyRecursive> Base;
+
+    bool TraverseCallExpr(CallExpr *E) {
+      const Decl *D = E->getCalleeDecl();
+      if (!D)
+        return true;
+      AsmLabelAttr *Attr = D->getAttr<AsmLabelAttr>();
+      if (!Attr)
+        return true;
+      if (Name == Attr->getLabel()) {
+        Result = true;
+        return false;
+      }
+      return true;
+    }
+  };
+}
+
+// isTriviallyRecursiveViaAsm - Check if this function calls another
+// decl that, because of the asm attribute, ends up pointing to itself.
+bool
+CodeGenModule::isTriviallyRecursiveViaAsm(const FunctionDecl *F) {
+  if (getCXXABI().getMangleContext().shouldMangleDeclName(F))
+    return false;
+
+  FunctionIsDirectlyRecursive Walker(F);
+  Walker.TraverseFunctionDecl(const_cast<FunctionDecl*>(F));
+  return Walker.Result;
+}
+
+bool
+CodeGenModule::shouldEmitFunction(const FunctionDecl *F) {
+  if (getFunctionLinkage(F) != llvm::Function::AvailableExternallyLinkage)
+    return true;
+  if (CodeGenOpts.OptimizationLevel == 0 &&
+      !F->hasAttr<AlwaysInlineAttr>())
+    return false;
+  // PR9614. Avoid cases where the source code is lying to us. An available
+  // externally function should have an equivalent function somewhere else,
+  // but a function that calls itself is clearly not equivalent to the real
+  // implementation.
+  // This happens in glibc's btowc and in some configure checks.
+  return !isTriviallyRecursiveViaAsm(F);
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
   const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
 
@@ -868,10 +922,7 @@ void CodeGenModule::EmitGlobalDefinition
   if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
     // At -O0, don't generate IR for functions with available_externally 
     // linkage.
-    if (CodeGenOpts.OptimizationLevel == 0 && 
-        !Function->hasAttr<AlwaysInlineAttr>() &&
-        getFunctionLinkage(Function) 
-                                  == llvm::Function::AvailableExternallyLinkage)
+    if (!shouldEmitFunction(Function))
       return;
 
     if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {

Modified: vendor/clang/dist/lib/CodeGen/CodeGenModule.h
==============================================================================
--- vendor/clang/dist/lib/CodeGen/CodeGenModule.h	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/lib/CodeGen/CodeGenModule.h	Fri Dec  9 18:30:42 2011	(r228366)
@@ -324,6 +324,8 @@ class CodeGenModule : public CodeGenType
   void createOpenCLRuntime();
   void createCUDARuntime();
 
+  bool isTriviallyRecursiveViaAsm(const FunctionDecl *F);
+  bool shouldEmitFunction(const FunctionDecl *F);
   llvm::LLVMContext &VMContext;
 
   /// @name Cache for Blocks Runtime Globals

Modified: vendor/clang/dist/lib/Driver/CMakeLists.txt
==============================================================================
--- vendor/clang/dist/lib/Driver/CMakeLists.txt	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/lib/Driver/CMakeLists.txt	Fri Dec  9 18:30:42 2011	(r228366)
@@ -21,5 +21,13 @@ add_clang_library(clangDriver
   Types.cpp
   )
 
+IF(MSVC)
+  get_target_property(NON_ANSI_COMPILE_FLAGS clangDriver COMPILE_FLAGS)
+  string(REPLACE /Za
+    "" NON_ANSI_COMPILE_FLAGS
+    ${NON_ANSI_COMPILE_FLAGS})
+  set_target_properties(clangDriver PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
+ENDIF(MSVC)
+
 add_dependencies(clangDriver ClangAttrList ClangDiagnosticDriver
                  ClangDriverOptions ClangCC1Options ClangCC1AsOptions)

Modified: vendor/clang/dist/lib/Driver/ToolChain.cpp
==============================================================================
--- vendor/clang/dist/lib/Driver/ToolChain.cpp	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/lib/Driver/ToolChain.cpp	Fri Dec  9 18:30:42 2011	(r228366)
@@ -211,6 +211,11 @@ std::string ToolChain::ComputeEffectiveC
   return ComputeLLVMTriple(Args, InputType);
 }
 
+void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+                                          ArgStringList &CC1Args) const {
+  // Each toolchain should provide the appropriate include flags.
+}
+
 ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
   if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
     StringRef Value = A->getValue(Args);
@@ -225,24 +230,18 @@ ToolChain::CXXStdlibType ToolChain::GetC
   return ToolChain::CST_Libstdcxx;
 }
 
-void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
-                                             ArgStringList &CmdArgs,
-                                             bool ObjCXXAutoRefCount) const {
-  CXXStdlibType Type = GetCXXStdlibType(Args);
-
-  // Header search paths are handled by the mass of goop in InitHeaderSearch.
-
-  switch (Type) {
-  case ToolChain::CST_Libcxx:
-    if (ObjCXXAutoRefCount)
-      CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
-    break;
-
-  case ToolChain::CST_Libstdcxx:
-    if (ObjCXXAutoRefCount)
-      CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
-    break;
-  }
+void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+                                             ArgStringList &CC1Args) const {
+  // Header search paths should be handled by each of the subclasses.
+  // Historically, they have not been, and instead have been handled inside of
+  // the CC1-layer frontend. As the logic is hoisted out, this generic function
+  // will slowly stop being called.
+  //
+  // While it is being called, replicate a bit of a hack to propagate the
+  // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
+  // header search paths with it. Once all systems are overriding this
+  // function, the CC1 flag and this line can be removed.
+  DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
 }
 
 void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,

Modified: vendor/clang/dist/lib/Driver/ToolChains.cpp
==============================================================================
--- vendor/clang/dist/lib/Driver/ToolChains.cpp	Fri Dec  9 18:30:06 2011	(r228365)
+++ vendor/clang/dist/lib/Driver/ToolChains.cpp	Fri Dec  9 18:30:42 2011	(r228366)
@@ -40,10 +40,51 @@
 
 #include "llvm/Config/config.h" // for CXX_INCLUDE_ROOT
 
+// Include the necessary headers to interface with the Windows registry and
+// environment.
+#ifdef _MSC_VER
+  #define WIN32_LEAN_AND_MEAN 1
+  #include <Windows.h>
+  #undef min
+  #undef max
+#endif
+
 using namespace clang::driver;
 using namespace clang::driver::toolchains;
 using namespace clang;
 
+/// \brief Utility function to add a system include directory to CC1 arguments.
+static void addSystemInclude(const ArgList &DriverArgs, ArgStringList &CC1Args,
+                             const Twine &Path) {
+  CC1Args.push_back("-internal-isystem");
+  CC1Args.push_back(DriverArgs.MakeArgString(Path));
+}
+
+/// \brief Utility function to add a system include directory with extern "C"
+/// semantics to CC1 arguments.
+///
+/// Note that this should be used rarely, and only for directories that
+/// historically and for legacy reasons are treated as having implicit extern
+/// "C" semantics. These semantics are *ignored* by and large today, but its
+/// important to preserve the preprocessor changes resulting from the
+/// classification.
+static void addExternCSystemInclude(const ArgList &DriverArgs,
+                                    ArgStringList &CC1Args, const Twine &Path) {
+  CC1Args.push_back("-internal-externc-isystem");
+  CC1Args.push_back(DriverArgs.MakeArgString(Path));
+}
+
+/// \brief Utility function to add a list of system include directories to CC1.
+static void addSystemIncludes(const ArgList &DriverArgs,
+                              ArgStringList &CC1Args,
+                              ArrayRef<StringRef> Paths) {
+  for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end();
+       I != E; ++I) {
+    CC1Args.push_back("-internal-isystem");
+    CC1Args.push_back(DriverArgs.MakeArgString(*I));
+  }
+}
+
 /// Darwin - Darwin tool chain for i386 and x86_64.
 
 Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple)
@@ -1385,19 +1426,6 @@ static bool IsUbuntu(enum LinuxDistro Di
          Distro == UbuntuNatty  || Distro == UbuntuOneiric;
 }
 
-// FIXME: This should be deleted. We should assume a multilib environment, and
-// fallback gracefully if any parts of it are absent.
-static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) {
-  if (Arch == llvm::Triple::x86_64) {
-    bool Exists;
-    if (Distro == Exherbo &&
-        (llvm::sys::fs::exists("/usr/lib32/libc.so", Exists) || !Exists))
-      return false;
-  }
-
-  return true;
-}
-
 static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {
   llvm::OwningPtr<llvm::MemoryBuffer> File;
   if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) {
@@ -1482,280 +1510,293 @@ static LinuxDistro DetectLinuxDistro(llv
   return UnknownDistro;
 }
 
-/// \brief Trivial helper function to simplify code checking path existence.
-static bool PathExists(StringRef Path) {
-  bool Exists;
-  if (!llvm::sys::fs::exists(Path, Exists))
-    return Exists;
-  return false;
+/// \brief Parse a GCCVersion object out of a string of text.
+///
+/// This is the primary means of forming GCCVersion objects.
+/*static*/ Linux::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) {
+  const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "" };
+  std::pair<StringRef, StringRef> First = VersionText.split('.');
+  std::pair<StringRef, StringRef> Second = First.second.split('.');
+
+  GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "" };
+  if (First.first.getAsInteger(10, GoodVersion.Major) ||
+      GoodVersion.Major < 0)
+    return BadVersion;
+  if (Second.first.getAsInteger(10, GoodVersion.Minor) ||
+      GoodVersion.Minor < 0)
+    return BadVersion;
+
+  // First look for a number prefix and parse that if present. Otherwise just
+  // stash the entire patch string in the suffix, and leave the number
+  // unspecified. This covers versions strings such as:
+  //   4.4
+  //   4.4.0
+  //   4.4.x
+  //   4.4.2-rc4
+  //   4.4.x-patched
+  // And retains any patch number it finds.
+  StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str();
+  if (!PatchText.empty()) {
+    if (unsigned EndNumber = PatchText.find_first_not_of("0123456789")) {
+      // Try to parse the number and any suffix.
+      if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
+          GoodVersion.Patch < 0)
+        return BadVersion;
+      GoodVersion.PatchSuffix = PatchText.substr(EndNumber).str();
+    }
+  }
+
+  return GoodVersion;
 }
 
-namespace {
-/// \brief This is a class to find a viable GCC installation for Clang to use.
-///
-/// This class tries to find a GCC installation on the system, and report
-/// information about it. It starts from the host information provided to the
-/// Driver, and has logic for fuzzing that where appropriate.
-class GCCInstallationDetector {
-  /// \brief Struct to store and manipulate GCC versions.
-  ///
-  /// We rely on assumptions about the form and structure of GCC version
-  /// numbers: they consist of at most three '.'-separated components, and each
-  /// component is a non-negative integer.
-  struct GCCVersion {
-    unsigned Major, Minor, Patch;
-
-    static GCCVersion Parse(StringRef VersionText) {
-      const GCCVersion BadVersion = {0, 0, 0};
-      std::pair<StringRef, StringRef> First = VersionText.split('.');
-      std::pair<StringRef, StringRef> Second = First.second.split('.');
+/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering.
+bool Linux::GCCVersion::operator<(const GCCVersion &RHS) const {
+  if (Major < RHS.Major) return true; if (Major > RHS.Major) return false;
+  if (Minor < RHS.Minor) return true; if (Minor > RHS.Minor) return false;
 
-      GCCVersion GoodVersion = {0, 0, 0};
-      if (First.first.getAsInteger(10, GoodVersion.Major))
-        return BadVersion;
-      if (Second.first.getAsInteger(10, GoodVersion.Minor))
-        return BadVersion;
-      // We accept a number, or a string for the patch version, in case there
-      // is a strang suffix, or other mangling: '4.1.x', '4.1.2-rc3'. When it
-      // isn't a number, we just use '0' as the number but accept it.
-      if (Second.first.getAsInteger(10, GoodVersion.Patch))
-        GoodVersion.Patch = 0;
-      return GoodVersion;
-    }
-
-    bool operator<(const GCCVersion &RHS) const {
-      if (Major < RHS.Major) return true;
-      if (Major > RHS.Major) return false;
-      if (Minor < RHS.Minor) return true;
-      if (Minor > RHS.Minor) return false;
-      return Patch < RHS.Patch;
-    }
-    bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
-    bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
-    bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
-  };
+  // Note that we rank versions with *no* patch specified is better than ones
+  // hard-coding a patch version. Thus if the RHS has no patch, it always
+  // wins, and the LHS only wins if it has no patch and the RHS does have
+  // a patch.
+  if (RHS.Patch == -1) return true;   if (Patch == -1) return false;
+  if (Patch < RHS.Patch) return true; if (Patch > RHS.Patch) return false;
 
-  bool IsValid;
-  std::string GccTriple;
+  // Finally, between completely tied version numbers, the version with the
+  // suffix loses as we prefer full releases.
+  if (RHS.PatchSuffix.empty()) return true;
+  return false;
+}
 
-  // FIXME: These might be better as path objects.
-  std::string GccInstallPath;
-  std::string GccParentLibPath;
-
-  llvm::SmallString<128> CxxIncludeRoot;
-
-public:
-  /// \brief Construct a GCCInstallationDetector from the driver.
-  ///
-  /// This performs all of the autodetection and sets up the various paths.
-  /// Once constructed, a GCCInstallation is esentially immutable.
-  GCCInstallationDetector(const Driver &D)
-    : IsValid(false),
-      GccTriple(D.DefaultHostTriple),
-      CxxIncludeRoot(CXX_INCLUDE_ROOT) {
-    // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but
-    // avoids adding yet another option to configure/cmake.
-    // It would probably be cleaner to break it in two variables
-    // CXX_GCC_ROOT with just /foo/bar
-    // CXX_GCC_VER with 4.5.2
-    // Then we would have
-    // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER
-    // and this function would return
-    // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER
-    if (CxxIncludeRoot != "") {
-      // This is of the form /foo/bar/include/c++/4.5.2/
-      if (CxxIncludeRoot.back() == '/')
-        llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the /
-      StringRef Version = llvm::sys::path::filename(CxxIncludeRoot);
-      llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version
-      llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++
-      llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include
-      GccInstallPath = CxxIncludeRoot.str();
-      GccInstallPath.append("/lib/gcc/");
-      GccInstallPath.append(CXX_INCLUDE_ARCH);
-      GccInstallPath.append("/");
-      GccInstallPath.append(Version);
-      GccParentLibPath = GccInstallPath + "/../../..";
-      IsValid = true;
-      return;
-    }
+/// \brief Construct a GCCInstallationDetector from the driver.
+///
+/// This performs all of the autodetection and sets up the various paths.
+/// Once constructed, a GCCInstallation is esentially immutable.
+Linux::GCCInstallationDetector::GCCInstallationDetector(const Driver &D)
+  : IsValid(false),
+    GccTriple(D.DefaultHostTriple) {
+  // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but
+  // avoids adding yet another option to configure/cmake.
+  // It would probably be cleaner to break it in two variables
+  // CXX_GCC_ROOT with just /foo/bar
+  // CXX_GCC_VER with 4.5.2
+  // Then we would have
+  // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER
+  // and this function would return
+  // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER
+  llvm::SmallString<128> CxxIncludeRoot(CXX_INCLUDE_ROOT);
+  if (CxxIncludeRoot != "") {
+    // This is of the form /foo/bar/include/c++/4.5.2/
+    if (CxxIncludeRoot.back() == '/')
+      llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the /
+    StringRef Version = llvm::sys::path::filename(CxxIncludeRoot);
+    llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version
+    llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++
+    llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include
+    GccInstallPath = CxxIncludeRoot.str();
+    GccInstallPath.append("/lib/gcc/");
+    GccInstallPath.append(CXX_INCLUDE_ARCH);
+    GccInstallPath.append("/");
+    GccInstallPath.append(Version);
+    GccParentLibPath = GccInstallPath + "/../../..";
+    IsValid = true;
+    return;
+  }
 
-    llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch();
-    // The library directories which may contain GCC installations.
-    SmallVector<StringRef, 4> CandidateLibDirs;
-    // The compatible GCC triples for this particular architecture.
-    SmallVector<StringRef, 10> CandidateTriples;
-    CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples);
-
-    // Always include the default host triple as the final fallback if no
-    // specific triple is detected.
-    CandidateTriples.push_back(D.DefaultHostTriple);
-
-    // Compute the set of prefixes for our search.
-    SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
-                                         D.PrefixDirs.end());
-    Prefixes.push_back(D.SysRoot);
-    Prefixes.push_back(D.SysRoot + "/usr");
-    Prefixes.push_back(D.InstalledDir + "/..");
-
-    // Loop over the various components which exist and select the best GCC
-    // installation available. GCC installs are ranked by version number.
-    GCCVersion BestVersion = {0, 0, 0};
-    for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
-      if (!PathExists(Prefixes[i]))
+  llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch();
+  // The library directories which may contain GCC installations.
+  SmallVector<StringRef, 4> CandidateLibDirs;
+  // The compatible GCC triples for this particular architecture.
+  SmallVector<StringRef, 10> CandidateTriples;
+  CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples);
+
+  // Always include the default host triple as the final fallback if no
+  // specific triple is detected.
+  CandidateTriples.push_back(D.DefaultHostTriple);
+
+  // Compute the set of prefixes for our search.
+  SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
+                                       D.PrefixDirs.end());
+  Prefixes.push_back(D.SysRoot);
+  Prefixes.push_back(D.SysRoot + "/usr");
+  Prefixes.push_back(D.InstalledDir + "/..");
+
+  // Loop over the various components which exist and select the best GCC
+  // installation available. GCC installs are ranked by version number.
+  Version = GCCVersion::Parse("0.0.0");
+  for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
+    if (!llvm::sys::fs::exists(Prefixes[i]))
+      continue;
+    for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) {
+      const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str();
+      if (!llvm::sys::fs::exists(LibDir))
         continue;
-      for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) {
-        const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str();
-        if (!PathExists(LibDir))
-          continue;
-        for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k)
-          ScanLibDirForGCCTriple(LibDir, CandidateTriples[k], BestVersion);
-      }
+      for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k)
+        ScanLibDirForGCCTriple(HostArch, LibDir, CandidateTriples[k]);
     }
   }
+}
 
-  /// \brief Check whether we detected a valid GCC install.
-  bool isValid() const { return IsValid; }
-
-  /// \brief Get the GCC triple for the detected install.
-  const std::string &getTriple() const { return GccTriple; }
-
-  /// \brief Get the detected GCC installation path.
-  const std::string &getInstallPath() const { return GccInstallPath; }
-
-  /// \brief Get the detected GCC parent lib path.
-  const std::string &getParentLibPath() const { return GccParentLibPath; }
-
-private:
-  static void CollectLibDirsAndTriples(llvm::Triple::ArchType HostArch,
-                                       SmallVectorImpl<StringRef> &LibDirs,
-                                       SmallVectorImpl<StringRef> &Triples) {
-    if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) {
-      static const char *const ARMLibDirs[] = { "/lib" };
-      static const char *const ARMTriples[] = { "arm-linux-gnueabi" };
-      LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs));
-      Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples));
-    } else if (HostArch == llvm::Triple::x86_64) {
-      static const char *const X86_64LibDirs[] = { "/lib64", "/lib" };
-      static const char *const X86_64Triples[] = {
-        "x86_64-linux-gnu",
-        "x86_64-unknown-linux-gnu",
-        "x86_64-pc-linux-gnu",
-        "x86_64-redhat-linux6E",
-        "x86_64-redhat-linux",
-        "x86_64-suse-linux",
-        "x86_64-manbo-linux-gnu",
-        "x86_64-linux-gnu",
-        "x86_64-slackware-linux"
-      };
-      LibDirs.append(X86_64LibDirs,
-                     X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
-      Triples.append(X86_64Triples,
-                     X86_64Triples + llvm::array_lengthof(X86_64Triples));
-    } else if (HostArch == llvm::Triple::x86) {
-      static const char *const X86LibDirs[] = { "/lib32", "/lib" };
-      static const char *const X86Triples[] = {
-        "i686-linux-gnu",
-        "i386-linux-gnu",
-        "i686-pc-linux-gnu",
-        "i486-linux-gnu",
-        "i686-redhat-linux",
-        "i386-redhat-linux",
-        "i586-suse-linux",
-        "i486-slackware-linux"
-      };
-      LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs));
-      Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples));
-    } else if (HostArch == llvm::Triple::ppc) {
-      static const char *const PPCLibDirs[] = { "/lib32", "/lib" };
-      static const char *const PPCTriples[] = {
-        "powerpc-linux-gnu",
-        "powerpc-unknown-linux-gnu"
-      };
-      LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
-      Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples));
-    } else if (HostArch == llvm::Triple::ppc64) {
-      static const char *const PPC64LibDirs[] = { "/lib64", "/lib" };
-      static const char *const PPC64Triples[] = {
-        "powerpc64-unknown-linux-gnu"
-      };
-      LibDirs.append(PPC64LibDirs,
-                     PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
-      Triples.append(PPC64Triples,
-                     PPC64Triples + llvm::array_lengthof(PPC64Triples));
-    }
-  }
-
-  void ScanLibDirForGCCTriple(const std::string &LibDir,
-                              StringRef CandidateTriple,
-                              GCCVersion &BestVersion) {
-    // There are various different suffixes involving the triple we
-    // check for. We also record what is necessary to walk from each back
-    // up to the lib directory.
-    const std::string Suffixes[] = {
-      "/gcc/" + CandidateTriple.str(),
-      "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
-
-      // Ubuntu has a strange mis-matched pair of triples that this happens to
-      // match.
-      // FIXME: It may be worthwhile to generalize this and look for a second
-      // triple.
-      "/" + CandidateTriple.str() + "/gcc/i686-linux-gnu"
+/*static*/ void Linux::GCCInstallationDetector::CollectLibDirsAndTriples(
+    llvm::Triple::ArchType HostArch, SmallVectorImpl<StringRef> &LibDirs,
+    SmallVectorImpl<StringRef> &Triples) {
+  if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) {
+    static const char *const ARMLibDirs[] = { "/lib" };
+    static const char *const ARMTriples[] = { "arm-linux-gnueabi" };
+    LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs));
+    Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples));
+  } else if (HostArch == llvm::Triple::x86_64) {
+    static const char *const X86_64LibDirs[] = { "/lib64", "/lib" };
+    static const char *const X86_64Triples[] = {
+      "x86_64-linux-gnu",
+      "x86_64-unknown-linux-gnu",
+      "x86_64-pc-linux-gnu",
+      "x86_64-redhat-linux6E",
+      "x86_64-redhat-linux",
+      "x86_64-suse-linux",
+      "x86_64-manbo-linux-gnu",
+      "x86_64-linux-gnu",
+      "x86_64-slackware-linux"
     };
-    const std::string InstallSuffixes[] = {
-      "/../../..",
-      "/../../../..",
-      "/../../../.."
+    LibDirs.append(X86_64LibDirs,
+                   X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
+    Triples.append(X86_64Triples,
+                   X86_64Triples + llvm::array_lengthof(X86_64Triples));
+  } else if (HostArch == llvm::Triple::x86) {
+    static const char *const X86LibDirs[] = { "/lib32", "/lib" };
+    static const char *const X86Triples[] = {
+      "i686-linux-gnu",
+      "i686-pc-linux-gnu",
+      "i486-linux-gnu",
+      "i386-linux-gnu",
+      "i686-redhat-linux",
+      "i586-redhat-linux",
+      "i386-redhat-linux",
+      "i586-suse-linux",
+      "i486-slackware-linux"
     };
-    // Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
-    const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) -
-                                  (CandidateTriple != "i386-linux-gnu"));
-    for (unsigned i = 0; i < NumSuffixes; ++i) {
-      StringRef Suffix = Suffixes[i];
-      llvm::error_code EC;
-      for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE;
-           !EC && LI != LE; LI = LI.increment(EC)) {
-        StringRef VersionText = llvm::sys::path::filename(LI->path());
-        GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
-        static const GCCVersion MinVersion = { 4, 1, 1 };
-        if (CandidateVersion < MinVersion)
-          continue;
-        if (CandidateVersion <= BestVersion)
-          continue;
-        if (!PathExists(LI->path() + "/crtbegin.o"))
-          continue;
+    LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs));
+    Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples));
+  } else if (HostArch == llvm::Triple::ppc) {
+    static const char *const PPCLibDirs[] = { "/lib32", "/lib" };
+    static const char *const PPCTriples[] = {
+      "powerpc-linux-gnu",
+      "powerpc-unknown-linux-gnu"
+    };
+    LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
+    Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples));
+  } else if (HostArch == llvm::Triple::ppc64) {
+    static const char *const PPC64LibDirs[] = { "/lib64", "/lib" };
+    static const char *const PPC64Triples[] = {
+      "powerpc64-unknown-linux-gnu"
+    };
+    LibDirs.append(PPC64LibDirs,
+                   PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
+    Triples.append(PPC64Triples,
+                   PPC64Triples + llvm::array_lengthof(PPC64Triples));
+  }
+}
 
-        BestVersion = CandidateVersion;
-        GccTriple = CandidateTriple.str();
-        // FIXME: We hack together the directory name here instead of
-        // using LI to ensure stable path separators across Windows and
-        // Linux.
-        GccInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str();
-        GccParentLibPath = GccInstallPath + InstallSuffixes[i];
-        IsValid = true;
-      }
+void Linux::GCCInstallationDetector::ScanLibDirForGCCTriple(
+    llvm::Triple::ArchType HostArch, const std::string &LibDir,
+    StringRef CandidateTriple) {
+  // There are various different suffixes involving the triple we
+  // check for. We also record what is necessary to walk from each back
+  // up to the lib directory.
+  const std::string Suffixes[] = {
+    "/gcc/" + CandidateTriple.str(),
+    "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
+
+    // Ubuntu has a strange mis-matched pair of triples that this happens to
+    // match.
+    // FIXME: It may be worthwhile to generalize this and look for a second
+    // triple.
+    "/i386-linux-gnu/gcc/" + CandidateTriple.str()
+  };
+  const std::string InstallSuffixes[] = {
+    "/../../..",
+    "/../../../..",
+    "/../../../.."
+  };
+  // Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
+  const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) -
+                                (HostArch != llvm::Triple::x86));
+  for (unsigned i = 0; i < NumSuffixes; ++i) {
+    StringRef Suffix = Suffixes[i];
+    llvm::error_code EC;
+    for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE;
+         !EC && LI != LE; LI = LI.increment(EC)) {
+      StringRef VersionText = llvm::sys::path::filename(LI->path());
+      GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
+      static const GCCVersion MinVersion = { "4.1.1", 4, 1, 1, "" };
+      if (CandidateVersion < MinVersion)
+        continue;
+      if (CandidateVersion <= Version)
+        continue;
+      if (!llvm::sys::fs::exists(LI->path() + "/crtbegin.o"))
+        continue;
+
+      Version = CandidateVersion;
+      GccTriple = CandidateTriple.str();
+      // FIXME: We hack together the directory name here instead of
+      // using LI to ensure stable path separators across Windows and
+      // Linux.
+      GccInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str();
+      GccParentLibPath = GccInstallPath + InstallSuffixes[i];
+      IsValid = true;
     }
   }
-};
 }
 
-static void addPathIfExists(const std::string &Path,
-                            ToolChain::path_list &Paths) {
-  if (PathExists(Path)) Paths.push_back(Path);
+static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) {
+  if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str());
+}
+
+/// \brief Get our best guess at the multiarch triple for a target.
+///
+/// Debian-based systems are starting to use a multiarch setup where they use
+/// a target-triple directory in the library and header search paths.
+/// Unfortunately, this triple does not align with the vanilla target triple,
+/// so we provide a rough mapping here.
+static std::string getMultiarchTriple(const llvm::Triple TargetTriple,
+                                      StringRef SysRoot) {
+  // For most architectures, just use whatever we have rather than trying to be
+  // clever.
+  switch (TargetTriple.getArch()) {
+  default:
+    return TargetTriple.str();
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list