[cfe-dev] extern "C" support

Mike Stump mrs at apple.com
Fri Dec 21 14:07:58 PST 2007


This adds initial extern "C" support...  It includes ast, sema, ast  
printer, and stub codegen but does not include ast dumper.

Thoughts?

Doing diffs in .:
--- ./AST/Decl.cpp.~1~	2007-12-20 15:32:21.000000000 -0800
+++ ./AST/Decl.cpp	2007-12-21 13:58:52.000000000 -0800
@@ -37,6 +37,7 @@ static unsigned nObjcImplementationDecls
  static unsigned nObjcCategoryImpl = 0;
  static unsigned nObjcCompatibleAlias = 0;
  static unsigned nObjcPropertyDecl = 0;
+static unsigned nLinkageSpecDecl = 0;

  static bool StatSwitch = false;

@@ -151,12 +152,28 @@ void Decl::PrintStats() {
  	  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 @@ void Decl::addDeclKind(const Kind k) {
      case PropertyDecl:
        nObjcPropertyDecl++;
        break;
+    case LinkageSpec:
+      nLinkageSpecDecl++;
+      break;
    }
  }

--- ./AST/DeclSerialization.cpp.~1~	2007-12-15 01:45:57.000000000 -0800
+++ ./AST/DeclSerialization.cpp	2007-12-21 13:58:52.000000000 -0800
@@ -422,3 +422,21 @@ TypedefDecl* TypedefDecl::CreateImpl(Des

    return decl;
  }
+
+// 
= 
= 
=---------------------------------------------------------------------- 
===//
+//      LinkageSpec Serialization.
+// 
= 
= 
=---------------------------------------------------------------------- 
===//
+
+void LinkageSpecDecl::EmitInRec(Serializer& S) const {
+  Decl::EmitInRec(S);
+  S.EmitInt(getLanguage());
+  S.EmitInt(inside_braces);
+  S.EmitPtr(D);
+}
+
+void LinkageSpecDecl::ReadInRec(Deserializer& D) {
+  Decl::ReadInRec(D);
+  language = static_cast<Language>(D.ReadInt());
+  inside_braces = static_cast<bool>(D.ReadInt());
+  D.ReadPtr(this->D);
+}
--- ./CodeGen/ModuleBuilder.cpp.~1~	2007-12-15 01:46:02.000000000 -0800
+++ ./CodeGen/ModuleBuilder.cpp	2007-12-21 13:58:52.000000000 -0800
@@ -34,6 +34,10 @@ void clang::CodeGen::CodeGenFunction(Cod
    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);
--- ./Driver/ASTConsumers.cpp.~1~	2007-12-20 15:32:21.000000000 -0800
+++ ./Driver/ASTConsumers.cpp	2007-12-21 13:58:52.000000000 -0800
@@ -35,8 +35,10 @@ namespace {
      DeclPrinter(std::ostream* out) : Out(out ? *out :  
*llvm::cerr.stream()) {}
      DeclPrinter() : Out(*llvm::cerr.stream()) {}

+    void PrintDecl(Decl *D);
      void PrintFunctionDeclStart(FunctionDecl *FD);
      void PrintTypeDefDecl(TypedefDecl *TD);
+    void PrintLinkageSpec(LinkageSpecDecl *LS);
      void PrintObjcMethodDecl(ObjcMethodDecl *OMD);
      void PrintObjcImplementationDecl(ObjcImplementationDecl *OID);
      void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID);
@@ -47,6 +49,58 @@ namespace {
    };
  } // end anonymous namespace

+void DeclPrinter:: PrintDecl(Decl *D) {
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    PrintFunctionDeclStart(FD);
+
+    if (FD->getBody()) {
+      Out << ' ';
+      FD->getBody()->printPretty(Out);
+      Out << '\n';
+    }
+  } else if (isa<ObjcMethodDecl>(D)) {
+    // Do nothing, methods definitions are printed in
+    // PrintObjcImplementationDecl.
+  } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+    PrintTypeDefDecl(TD);
+  } else if (ObjcInterfaceDecl *OID = dyn_cast<ObjcInterfaceDecl>(D)) {
+    PrintObjcInterfaceDecl(OID);
+  } else if (ObjcProtocolDecl *PID = dyn_cast<ObjcProtocolDecl>(D)) {
+    PrintObjcProtocolDecl(PID);
+  } else if (ObjcForwardProtocolDecl *OFPD =
+	     dyn_cast<ObjcForwardProtocolDecl>(D)) {
+    Out << "@protocol ";
+    for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
+      const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
+      if (i) Out << ", ";
+      Out << D->getName();
+    }
+    Out << ";\n";
+  } else if (ObjcImplementationDecl *OID =
+	     dyn_cast<ObjcImplementationDecl>(D)) {
+    PrintObjcImplementationDecl(OID);
+  } else if (ObjcCategoryImplDecl *OID =
+	     dyn_cast<ObjcCategoryImplDecl>(D)) {
+    PrintObjcCategoryImplDecl(OID);
+  } else if (ObjcCategoryDecl *OID =
+	     dyn_cast<ObjcCategoryDecl>(D)) {
+    PrintObjcCategoryDecl(OID);
+  } else if (ObjcCompatibleAliasDecl *OID =
+	     dyn_cast<ObjcCompatibleAliasDecl>(D)) {
+    PrintObjcCompatibleAliasDecl(OID);
+  } else if (isa<ObjcClassDecl>(D)) {
+    Out << "@class [printing todo]\n";
+  } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+    Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
+  } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
+    Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
+  } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
+    PrintLinkageSpec(LSD);
+  } else {
+    assert(0 && "Unknown decl type!");
+  }
+}
+
  void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
    bool HasBody = FD->getBody();

@@ -100,6 +154,21 @@ void DeclPrinter::PrintTypeDefDecl(Typed
    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());
+  if (LS->is_inside_braces())
+    Out << "}\n";
+}
+
  void DeclPrinter::PrintObjcMethodDecl(ObjcMethodDecl *OMD) {
    if (OMD->isInstance())
      Out << "\n- ";
@@ -294,53 +363,7 @@ namespace {
      ASTPrinter(std::ostream* o = NULL) : DeclPrinter(o) {}

      virtual void HandleTopLevelDecl(Decl *D) {
-      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-        PrintFunctionDeclStart(FD);
-
-        if (FD->getBody()) {
-          Out << ' ';
-          FD->getBody()->printPretty(Out);
-          Out << '\n';
-        }
-      } else if (isa<ObjcMethodDecl>(D)) {
-	    // Do nothing, methods definitions are printed in
-		// PrintObjcImplementationDecl.
-      } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
-        PrintTypeDefDecl(TD);
-      } else if (ObjcInterfaceDecl *OID =  
dyn_cast<ObjcInterfaceDecl>(D)) {
-        PrintObjcInterfaceDecl(OID);
-      } else if (ObjcProtocolDecl *PID =  
dyn_cast<ObjcProtocolDecl>(D)) {
-        PrintObjcProtocolDecl(PID);
-      } else if (ObjcForwardProtocolDecl *OFPD =
-                     dyn_cast<ObjcForwardProtocolDecl>(D)) {
-        Out << "@protocol ";
-        for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; + 
+i) {
-          const ObjcProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
-          if (i) Out << ", ";
-          Out << D->getName();
-        }
-        Out << ";\n";
-      } else if (ObjcImplementationDecl *OID =
-                   dyn_cast<ObjcImplementationDecl>(D)) {
-        PrintObjcImplementationDecl(OID);
-      } else if (ObjcCategoryImplDecl *OID =
-                 dyn_cast<ObjcCategoryImplDecl>(D)) {
-        PrintObjcCategoryImplDecl(OID);
-      } else if (ObjcCategoryDecl *OID =
-                 dyn_cast<ObjcCategoryDecl>(D)) {
-        PrintObjcCategoryDecl(OID);
-      } else if (ObjcCompatibleAliasDecl *OID =
-                 dyn_cast<ObjcCompatibleAliasDecl>(D)) {
-        PrintObjcCompatibleAliasDecl(OID);
-      } else if (isa<ObjcClassDecl>(D)) {
-        Out << "@class [printing todo]\n";
-      } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
-        Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
-      } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
-        Out << "Read top-level variable decl: '" << SD->getName() <<  
"'\n";
-      } else {
-        assert(0 && "Unknown decl type!");
-      }
+      PrintDecl(D);
      }
    };
  }
@@ -586,6 +609,8 @@ namespace {
          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.
--- ./include/clang/AST/Decl.h.~1~	2007-12-19 20:43:53.000000000 -0800
+++ ./include/clang/AST/Decl.h	2007-12-21 13:58:52.000000000 -0800
@@ -70,6 +70,7 @@ public:
           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 @@ protected:
    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
--- ./include/clang/AST/Type.h.~1~	2007-12-19 20:43:53.000000000 -0800
+++ ./include/clang/AST/Type.h	2007-12-21 13:58:52.000000000 -0800
@@ -319,7 +319,7 @@ public:
    /// 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;

--- ./include/clang/Basic/DiagnosticKinds.def.~1~	2007-12-19  
20:43:53.000000000 -0800
+++ ./include/clang/Basic/DiagnosticKinds.def	2007-12-21  
13:58:52.000000000 -0800
@@ -529,6 +529,8 @@ DIAG(err_invalid_reference_qualifier_app
       "'%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,
--- ./include/clang/CodeGen/ModuleBuilder.h.~1~	2007-12-15  
01:45:48.000000000 -0800
+++ ./include/clang/CodeGen/ModuleBuilder.h	2007-12-21  
13:58:52.000000000 -0800
@@ -22,6 +22,7 @@ namespace llvm {
  namespace clang {
    class ASTContext;
    class FunctionDecl;
+  class LinkageSpecDecl;
    class FileVarDecl;
    struct LangOptions;
    class Diagnostic;
@@ -37,6 +38,8 @@ namespace CodeGen {
    /// 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);
--- ./include/clang/Parse/Action.h.~1~	2007-12-15 01:45:54.000000000  
-0800
+++ ./include/clang/Parse/Action.h	2007-12-21 13:58:52.000000000 -0800
@@ -154,6 +154,11 @@ public:
    virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
      return 0;
    }
+
+  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, std::string,  
bool inside_braces,
+				   DeclTy *D) {
+    return 0;
+  }

    // 
===-------------------------------------------------------------------- 
===//
    // Type Parsing Callbacks.
--- ./include/clang/Parse/Parser.h.~1~	2007-12-15 01:45:54.000000000  
-0800
+++ ./include/clang/Parse/Parser.h	2007-12-21 13:58:52.000000000 -0800
@@ -434,6 +434,7 @@ private:
    // C++ 7: Declarations [dcl.dcl]

    DeclTy *ParseNamespace(unsigned Context);
+  DeclTy *ParseLinkage(unsigned Context);

  };

--- ./Parse/ParseDeclCXX.cpp.~1~	2007-12-20 16:45:00.000000000 -0800
+++ ./Parse/ParseDeclCXX.cpp	2007-12-21 13:58:52.000000000 -0800
@@ -80,3 +80,27 @@ Parser::DeclTy *Parser::ParseNamespace(u

    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, saw_braces, D);
+}
--- ./Parse/Parser.cpp.~1~	2007-12-15 01:46:02.000000000 -0800
+++ ./Parse/Parser.cpp	2007-12-21 13:58:52.000000000 -0800
@@ -378,6 +378,12 @@ Parser::DeclTy *Parser::ParseDeclaration
        return ParseObjCAtInterfaceDeclaration(AtLoc,  
DS.getAttributes());
    }

+  if (Tok.is(tok::string_literal)
+      && DS.getStorageClassSpec() == DeclSpec::SCS_extern)
+    {
+      return ParseLinkage(Declarator::FileContext);
+    }
+
    // Parse the first declarator.
    Declarator DeclaratorInfo(DS, Declarator::FileContext);
    ParseDeclarator(DeclaratorInfo);
--- ./Sema/Sema.h.~1~	2007-12-19 20:43:54.000000000 -0800
+++ ./Sema/Sema.h	2007-12-21 13:58:52.000000000 -0800
@@ -189,6 +189,8 @@ private:
    virtual void ObjcActOnStartOfMethodDef(Scope *S, DeclTy *D);

    virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtTy *Body);
+  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, std::string  
Lang,
+				   bool inside_braces, DeclTy *D);

    /// Scope actions.
    virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
--- ./Sema/SemaDecl.cpp.~1~	2007-12-19 20:43:54.000000000 -0800
+++ ./Sema/SemaDecl.cpp	2007-12-21 13:58:52.000000000 -0800
@@ -1649,6 +1649,25 @@ void Sema::ActOnEnumBody(SourceLocation
    Enum->defineElements(EltList, BestType);
  }

+Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc,
+				     std::string Lang,
+				     bool inside_brace,
+				     DeclTy *D) {
+  LinkageSpecDecl::Language language;
+  Decl *dcl = static_cast<Decl *>(D);
+  if (Lang == "\"C\"")
+    language = LinkageSpecDecl::lang_c;
+  else if (Lang == "\"C++\"")
+    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();
--------------




More information about the cfe-dev mailing list