Index: include/clang/Basic/DiagnosticKinds.def
===================================================================
--- include/clang/Basic/DiagnosticKinds.def	(revision 45481)
+++ include/clang/Basic/DiagnosticKinds.def	(working copy)
@@ -529,6 +529,8 @@
      "'%0' qualifier may not be applied to a reference")
 DIAG(err_declarator_need_ident, ERROR,
      "declarator requires an identifier")
+DIAG(err_bad_language, ERROR,
+     "unknown linkage language")
 
 // Attributes
 DIAG(err_attribute_wrong_number_arguments, ERROR,
Index: include/clang/CodeGen/ModuleBuilder.h
===================================================================
--- include/clang/CodeGen/ModuleBuilder.h	(revision 45481)
+++ include/clang/CodeGen/ModuleBuilder.h	(working copy)
@@ -22,6 +22,7 @@
 namespace clang {
   class ASTContext;
   class FunctionDecl;
+  class LinkageSpecDecl;
   class FileVarDecl;
   struct LangOptions;
   class Diagnostic;
@@ -37,6 +38,8 @@
   /// CodeGenFunction - Convert the AST node for a FunctionDecl into LLVM.
   ///
   void CodeGenFunction(CodeGenModule *Builder, FunctionDecl *D);
+
+  void CodeGenLinkageSpec(CodeGenModule *Builder, LinkageSpecDecl *LS);
   
   /// CodeGenGlobalVar - Emit the specified global variable to LLVM.
   void CodeGenGlobalVar(CodeGenModule *Builder, FileVarDecl *D);
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h	(revision 45481)
+++ include/clang/AST/ASTContext.h	(working copy)
@@ -30,6 +30,7 @@
   
 /// ASTContext - This class holds long-lived AST nodes (such as types and
 /// decls) that can be referred to throughout the semantic analysis of a file.
+
 class ASTContext {  
   std::vector<Type*> Types;
   llvm::FoldingSet<ComplexType> ComplexTypes;
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h	(revision 45481)
+++ include/clang/AST/Decl.h	(working copy)
@@ -70,6 +70,7 @@
          ObjcMethod,
          ObjcClass,
          ObjcForwardProtocol,
+	 LinkageSpec,
   
     // For each non-leaf class, we now define a mapping to the first/last member
     // of the class, to allow efficient classof.
@@ -753,6 +754,34 @@
   friend Decl* Decl::Create(llvm::Deserializer& D);
 };
 
+
+/// LinkageSpecDecl - This represents a linkage specification.
+class LinkageSpecDecl : public Decl {
+public:
+  enum Language { lang_cxx, lang_c };
+private:
+  /// Language - The language for this linkage specification.
+  Language language;
+  bool inside_braces;
+  Decl *D;
+public:
+  LinkageSpecDecl(SourceLocation L, Language lang, bool inside, Decl *d)
+   : Decl(LinkageSpec, L), language(lang), inside_braces(inside), D(d) {}
+  
+  Language getLanguage() const { return language; }
+  bool is_inside_braces() { return inside_braces; }
+  Decl *getD() { return D; }
+    
+  static bool classof(const Decl *D) {
+    return D->getKind() == LinkageSpec;
+  }
+  static bool classof(const LinkageSpecDecl *D) { return true; }
+  
+protected:
+  void EmitInRec(llvm::Serializer& S) const;
+  void ReadInRec(llvm::Deserializer& D);
+};
+
 }  // end namespace clang
 
 #endif
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h	(revision 45481)
+++ include/clang/AST/Type.h	(working copy)
@@ -319,7 +319,7 @@
   /// type type.  This takes off typedefs, typeof's etc.  If the outer level of
   /// the type is already concrete, it returns it unmodified.  This is similar
   /// to getting the canonical type, but it doesn't remove *all* typedefs.  For
-  /// example, it return "T*" as "T*", (not as "int*"), because the pointer is
+  /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
   /// concrete.
   const Type *getDesugaredType() const;
   
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 45481)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -434,6 +434,7 @@
   // C++ 7: Declarations [dcl.dcl]
   
   DeclTy *ParseNamespace(unsigned Context);
+  DeclTy *ParseLinkage(unsigned Context);
 
 };
 
Index: include/clang/Parse/Action.h
===================================================================
--- include/clang/Parse/Action.h	(revision 45481)
+++ include/clang/Parse/Action.h	(working copy)
@@ -154,6 +154,11 @@
   virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
     return 0;
   }
+
+  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *, bool inside_braces,
+				   DeclTy *D) {
+    return 0;
+  }
   
   //===--------------------------------------------------------------------===//
   // Type Parsing Callbacks.
Index: Sema/Sema.h
===================================================================
--- Sema/Sema.h	(revision 45481)
+++ Sema/Sema.h	(working copy)
@@ -190,6 +190,8 @@
   virtual void ObjcActOnStartOfMethodDef(Scope *S, DeclTy *D);
   
   virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtTy *Body);
+  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang,
+				   bool inside_braces, DeclTy *D);
   
   /// Scope actions.
   virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
Index: Sema/SemaDecl.cpp
===================================================================
--- Sema/SemaDecl.cpp	(revision 45481)
+++ Sema/SemaDecl.cpp	(working copy)
@@ -1649,6 +1649,25 @@
   Enum->defineElements(EltList, BestType);
 }
 
+Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc,
+				     const char *Lang,
+				     bool inside_brace,
+				     DeclTy *D) {
+  LinkageSpecDecl::Language language;
+  Decl *dcl = static_cast<Decl *>(D);
+  if (strcmp (Lang, "\"C\"") == 0)
+    language = LinkageSpecDecl::lang_c;
+  else if (strcmp (Lang, "\"C++\"") == 0)
+    language = LinkageSpecDecl::lang_cxx;
+  else
+    {
+      Diag(Loc, diag::err_bad_language);
+      return 0;
+    }
+  
+  return new LinkageSpecDecl(Loc, language, inside_brace, dcl);
+}
+
 void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) {
   const char *attrName = rawAttr->getAttributeName()->getName();
   unsigned attrLen = rawAttr->getAttributeName()->getLength();
Index: AST/Decl.cpp
===================================================================
--- AST/Decl.cpp	(revision 45481)
+++ AST/Decl.cpp	(working copy)
@@ -37,6 +37,7 @@
 static unsigned nObjcCategoryImpl = 0;
 static unsigned nObjcCompatibleAlias = 0;
 static unsigned nObjcPropertyDecl = 0;
+static unsigned nLinkageSpecDecl = 0;
 
 static bool StatSwitch = false;
 
@@ -151,12 +152,28 @@
 	  nObjcPropertyDecl, (int)sizeof(ObjcPropertyDecl),
 	  int(nObjcPropertyDecl*sizeof(ObjcPropertyDecl)));
   
+  fprintf(stderr, "    %d linkage specifications, %d each (%d bytes)\n", 
+	  nLinkageSpecDecl, (int)sizeof(LinkageSpecDecl),
+	  int(nLinkageSpecDecl*sizeof(LinkageSpecDecl)));
+  
   fprintf(stderr, "Total bytes = %d\n", 
 	  int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+
 	      nFileVars*sizeof(FileVarDecl)+nParmVars*sizeof(ParmVarDecl)+
 	      nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+
 	      nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+
-	      nTypedef*sizeof(TypedefDecl)) /* FIXME: add Objc decls */);
+	      nTypedef*sizeof(TypedefDecl)+
+	      nInterfaceDecls*sizeof(ObjcInterfaceDecl)+
+	      nIvarDecls*sizeof(ObjcIvarDecl)+
+	      nClassDecls*sizeof(ObjcClassDecl)+
+	      nMethodDecls*sizeof(ObjcMethodDecl)+
+	      nProtocolDecls*sizeof(ObjcProtocolDecl)+
+	      nForwardProtocolDecls*sizeof(ObjcForwardProtocolDecl)+
+	      nCategoryDecls*sizeof(ObjcCategoryDecl)+
+	      nObjcImplementationDecls*sizeof(ObjcImplementationDecl)+
+	      nObjcCategoryImpl*sizeof(ObjcCategoryImplDecl)+
+	      nObjcCompatibleAlias*sizeof(ObjcCompatibleAliasDecl)+
+	      nObjcPropertyDecl*sizeof(ObjcPropertyDecl)+
+	      nLinkageSpecDecl*sizeof(LinkageSpecDecl)));
 }
 
 void Decl::addDeclKind(const Kind k) {
@@ -223,6 +240,9 @@
     case PropertyDecl:
       nObjcPropertyDecl++;
       break;
+    case LinkageSpec:
+      nLinkageSpecDecl++;
+      break;
   }
 }
 
Index: Driver/clang.cpp
===================================================================
--- Driver/clang.cpp	(revision 45481)
+++ Driver/clang.cpp	(working copy)
@@ -798,35 +798,19 @@
   // FIXME: get these from the target?
   if (!nostdinc) {
     if (Lang.CPlusPlus) {
-      AddPath("/usr/include/c++/4.0.0", System, true, false, false, Headers);
-      AddPath("/usr/include/c++/4.0.0/i686-apple-darwin8", System, true, false,
+      AddPath("/usr/include/c++/4.0.2", System, true, false, false, Headers);
+      AddPath("/usr/include/c++/4.0.2/i386-redhat-linux", System, true, false,
               false, Headers);
-      AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false,
+      AddPath("/usr/include/c++/4.0.2/backward", System, true, false, false,
               Headers);
     }
     
     AddPath("/usr/local/include", System, false, false, false, Headers);
     // leopard
-    AddPath("/usr/lib/gcc/i686-apple-darwin9/4.0.1/include", System, 
+    AddPath("/usr/lib/gcc/i386-redhat-linux/4.0.2/include", System, 
             false, false, false, Headers);
-    AddPath("/usr/lib/gcc/powerpc-apple-darwin9/4.0.1/include", 
-            System, false, false, false, Headers);
-    AddPath("/usr/lib/gcc/powerpc-apple-darwin9/"
-            "4.0.1/../../../../powerpc-apple-darwin0/include", 
-            System, false, false, false, Headers);
 
-    // tiger
-    AddPath("/usr/lib/gcc/i686-apple-darwin8/4.0.1/include", System, 
-            false, false, false, Headers);
-    AddPath("/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include", 
-            System, false, false, false, Headers);
-    AddPath("/usr/lib/gcc/powerpc-apple-darwin8/"
-            "4.0.1/../../../../powerpc-apple-darwin8/include", 
-            System, false, false, false, Headers);
-
     AddPath("/usr/include", System, false, false, false, Headers);
-    AddPath("/System/Library/Frameworks", System, true, false, true, Headers);
-    AddPath("/Library/Frameworks", System, true, false, true, Headers);
   }
 
   // Now that we have collected all of the include paths, merge them all
Index: Driver/ASTConsumers.cpp
===================================================================
--- Driver/ASTConsumers.cpp	(revision 45481)
+++ Driver/ASTConsumers.cpp	(working copy)
@@ -38,6 +38,7 @@
     
     void PrintFunctionDeclStart(FunctionDecl *FD);    
     void PrintTypeDefDecl(TypedefDecl *TD);    
+    void PrintLinkageSpec(LinkageSpecDecl *LS);
     void PrintObjcMethodDecl(ObjcMethodDecl *OMD);    
     void PrintObjcImplementationDecl(ObjcImplementationDecl *OID);
     void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID);
@@ -101,6 +102,21 @@
   Out << "typedef " << S << ";\n";
 }
 
+void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
+  std::string l;
+  if (LS->getLanguage() == LinkageSpecDecl::lang_c)
+    l = "C";
+  else if (LS->getLanguage() == LinkageSpecDecl::lang_cxx)
+    l = "C++";
+  else assert(0 && "unknown language in linkage specification");
+  Out << "extern \"" << l << "\" ";
+  if (LS->is_inside_braces())
+    Out << "{\n";
+  //  PrintDecl(LS->getD());  // FIXME: bjornr: merging patch out of sync
+  if (LS->is_inside_braces())
+    Out << "}\n";
+}
+
 void DeclPrinter::PrintObjcMethodDecl(ObjcMethodDecl *OMD) {
   if (OMD->isInstance())
     Out << "\n- ";
@@ -589,6 +605,8 @@
         CodeGen::CodeGenFunction(Builder, FD);
       } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
         CodeGen::CodeGenGlobalVar(Builder, FVD);
+      } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
+        CodeGen::CodeGenLinkageSpec(Builder, LSD);
       } else {
         assert(isa<TypeDecl>(D) && "Only expected type decls here");
         // don't codegen for now, eventually pass down for debug info.
Index: CodeGen/ModuleBuilder.cpp
===================================================================
--- CodeGen/ModuleBuilder.cpp	(revision 45481)
+++ CodeGen/ModuleBuilder.cpp	(working copy)
@@ -34,6 +34,10 @@
   B->EmitFunction(D);
 }
 
+void clang::CodeGen::CodeGenLinkageSpec(CodeGenModule *B, LinkageSpecDecl *LS) {
+
+}
+
 /// CodeGenGlobalVar - Emit the specified global variable to LLVM.
 void clang::CodeGen::CodeGenGlobalVar(CodeGenModule *Builder, FileVarDecl *D) {
   Builder->EmitGlobalVarDeclarator(D);
Index: Parse/ParseDeclCXX.cpp
===================================================================
--- Parse/ParseDeclCXX.cpp	(revision 45481)
+++ Parse/ParseDeclCXX.cpp	(working copy)
@@ -80,3 +80,27 @@
   
   return 0;
 }
+
+// C++ 7.5p2
+Parser::DeclTy *Parser::ParseLinkage(unsigned Context) {
+  std::string lang = PP.getSpelling(Tok);
+  SourceLocation Loc = ConsumeStringToken ();
+  bool saw_braces = false;
+  DeclTy *D = 0;
+  
+  if (Tok.is(tok::l_brace))
+    {
+      SourceLocation LBrace = ConsumeBrace();
+      saw_braces = true;
+      while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+	// FIXME capture the decls.
+	D = ParseExternalDeclaration();
+      }
+
+      SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
+    }
+  else
+    D = ParseDeclaration(Context);
+
+  return Actions.ActOnLinkageSpec(Loc, lang.c_str(), saw_braces, D);
+}
Index: Parse/Parser.cpp
===================================================================
--- Parse/Parser.cpp	(revision 45481)
+++ Parse/Parser.cpp	(working copy)
@@ -381,6 +381,14 @@
     }
     return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()); 
   }
+
+  if (Tok.is(tok::string_literal)
+      && DS.getStorageClassSpec() == DeclSpec::SCS_extern
+      && DS.getParsedSpecifiers () == DeclSpec::PQ_StorageClassSpecifier)
+    {
+      return ParseLinkage(Declarator::FileContext);
+    }
+
   
   // Parse the first declarator.
   Declarator DeclaratorInfo(DS, Declarator::FileContext);
