]> granicus.if.org Git - clang/commitdiff
Add first pieces of support for parsing and representing
authorChris Lattner <sabre@nondot.org>
Sat, 12 Jan 2008 07:05:38 +0000 (07:05 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 12 Jan 2008 07:05:38 +0000 (07:05 +0000)
extern "C" in C++ mode.  Patch by Mike Stump!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45904 91177308-0d34-0410-b5e6-96231b3b80d8

15 files changed:
AST/Decl.cpp
AST/DeclSerialization.cpp
CodeGen/CodeGenModule.cpp
CodeGen/CodeGenModule.h
CodeGen/ModuleBuilder.cpp
Driver/ASTConsumers.cpp
Parse/ParseDeclCXX.cpp
Parse/Parser.cpp
Sema/Sema.h
Sema/SemaDecl.cpp
include/clang/AST/Decl.h
include/clang/Basic/DiagnosticKinds.def
include/clang/CodeGen/ModuleBuilder.h
include/clang/Parse/Action.h
include/clang/Parse/Parser.h

index f67d7124f5af95adf212d5a9b35e894a792e1680..bf1ffee83233d8c63937bb1047b271b348ab7ec1 100644 (file)
@@ -37,6 +37,7 @@ static unsigned nObjCImplementationDecls = 0;
 static unsigned nObjCCategoryImpl = 0;
 static unsigned nObjCCompatibleAlias = 0;
 static unsigned nObjCPropertyDecl = 0;
+static unsigned nLinkageSpecDecl = 0;
 
 static bool StatSwitch = false;
 
@@ -156,7 +157,9 @@ void Decl::PrintStats() {
              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)+
+             nLinkageSpecDecl*sizeof(LinkageSpecDecl))
+         /* FIXME: add ObjC decls */);
 }
 
 void Decl::addDeclKind(const Kind k) {
@@ -223,6 +226,9 @@ void Decl::addDeclKind(const Kind k) {
     case PropertyDecl:
       nObjCPropertyDecl++;
       break;
+    case LinkageSpec:
+      nLinkageSpecDecl++;
+      break;
   }
 }
 
index 6baa2626026555d2c00a6e72e9a724321004f170..146ebbacbe19331e43d57f300ca39f5a61453d7b 100644 (file)
@@ -422,3 +422,19 @@ TypedefDecl* TypedefDecl::CreateImpl(Deserializer& D) {
 
   return decl;
 }
+
+//===----------------------------------------------------------------------===//
+//      LinkageSpec Serialization.
+//===----------------------------------------------------------------------===//
+
+void LinkageSpecDecl::EmitInRec(Serializer& S) const {
+  Decl::EmitInRec(S);
+  S.EmitInt(getLanguage());
+  S.EmitPtr(D);
+}
+
+void LinkageSpecDecl::ReadInRec(Deserializer& D) {
+  Decl::ReadInRec(D);
+  Language = static_cast<LanguageIDs>(D.ReadInt());
+  D.ReadPtr(this->D);
+}
index 9a65d2e2967157fba70da7d1c3eb19efe810d235..bb61dc7cd8253e9c8b7cf46b3bf4fd85c6430211 100644 (file)
@@ -44,6 +44,16 @@ void CodeGenModule::WarnUnsupported(const Stmt *S, const char *Type) {
                     &Msg, 1, &Range, 1);
 }
 
+/// WarnUnsupported - Print out a warning that codegen doesn't support the
+/// specified decl yet.
+void CodeGenModule::WarnUnsupported(const Decl *D, const char *Type) {
+  unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Warning, 
+                                               "cannot codegen this %0 yet");
+  std::string Msg = Type;
+  getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID,
+                    &Msg, 1);
+}
+
 /// ReplaceMapValuesWith - This is a really slow and bad function that
 /// searches for any entries in GlobalDeclMap that point to OldVal, changing
 /// them to point to NewVal.  This is badbadbad, FIXME!
index 6653e508813e5ac5297e5b3e672439ce058133de..b86ceba426beb234bd9648945223f615bc092757 100644 (file)
@@ -95,6 +95,10 @@ public:
   /// specified stmt yet.
   void WarnUnsupported(const Stmt *S, const char *Type);
   
+  /// WarnUnsupported - Print out a warning that codegen doesn't support the
+  /// specified decl yet.
+  void WarnUnsupported(const Decl *D, const char *Type);
+  
 private:
   /// ReplaceMapValuesWith - This is a really slow and bad function that
   /// searches for any entries in GlobalDeclMap that point to OldVal, changing
index 49881c36d9405a3001a50c00545cb6166d5174e6..fff5b3fbfff2e045a27222512df018774adf4146 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "CodeGenModule.h"
+#include "clang/AST/Decl.h"
 using namespace clang;
 
 
@@ -34,6 +35,16 @@ void clang::CodeGen::CodeGenFunction(CodeGenModule *B, FunctionDecl *D) {
   B->EmitFunction(D);
 }
 
+/// CodeGenLinkageSpec - Emit the specified linkage space to LLVM.
+void clang::CodeGen::CodeGenLinkageSpec(CodeGenModule *Builder,
+                                       LinkageSpecDecl *LS) {
+  if (LS->getLanguage() == LinkageSpecDecl::lang_cxx)
+    Builder->WarnUnsupported(LS, "linkage spec");
+
+  // FIXME: implement C++ linkage, C linkage works mostly by C
+  // language reuse already.
+}
+
 /// CodeGenGlobalVar - Emit the specified global variable to LLVM.
 void clang::CodeGen::CodeGenGlobalVar(CodeGenModule *Builder, FileVarDecl *D) {
   Builder->EmitGlobalVarDeclarator(D);
index aa49e2adc548ec902f8db57b871c99a94ccbc109..1bbdf388c49940897608341303be1b07be1f0474 100644 (file)
@@ -39,6 +39,7 @@ namespace {
     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);
@@ -94,6 +95,8 @@ void DeclPrinter:: PrintDecl(Decl *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!");
   }
@@ -152,6 +155,18 @@ void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
   Out << "typedef " << S << ";\n";
 }
 
+void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
+  const char *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 << "\" { ";
+  PrintDecl(LS->getDecl());
+  Out << "}\n";
+}
+
 void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) {
   if (OMD->isInstance())
     Out << "\n- ";
@@ -608,6 +623,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.
index 20c1fab4fbe279f7aa4759034710c2ed6ebcc0ec..46dcb5748191552bab99cc824f3cc1952649cf04 100644 (file)
@@ -80,3 +80,40 @@ Parser::DeclTy *Parser::ParseNamespace(unsigned Context) {
   
   return 0;
 }
+
+/// ParseLinkage - We know that the current token is a string_literal
+/// and just before that, that extern was seen.
+///
+///       linkage-specification: [C++ 7.5p2: dcl.link]
+///         'extern' string-literal '{' declaration-seq[opt] '}'
+///         'extern' string-literal declaration
+///
+Parser::DeclTy *Parser::ParseLinkage(unsigned Context) {
+  assert(Tok.is(tok::string_literal) && "Not a stringliteral!");
+  llvm::SmallVector<char, 8> LangBuffer;
+  // LangBuffer is guaranteed to be big enough.
+  LangBuffer.resize(Tok.getLength());
+  const char *LangBufPtr = &LangBuffer[0];
+  unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);
+
+  SourceLocation Loc = ConsumeStringToken();
+  DeclTy *D = 0;
+  SourceLocation LBrace, RBrace;
+  
+  if (Tok.isNot(tok::l_brace)) {
+    D = ParseDeclaration(Context);
+  } else {
+    LBrace = ConsumeBrace();
+    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+      // FIXME capture the decls.
+      D = ParseExternalDeclaration();
+    }
+
+    RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
+  }
+
+  if (!D)
+    return 0;
+
+  return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, D);
+}
index cc2c5d90c9693bc89fc17e9dc1237eae761bf680..eeced570bb449abae4d99fe9e49b56779ebaa263 100644 (file)
@@ -386,6 +386,15 @@ Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() {
     return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()); 
   }
   
+  // If the declspec consisted only of 'extern' and we have a string
+  // literal following it, this must be a C++ linkage specifier like
+  // 'extern "C"'.
+  // FIXME: This should be limited to just C++/ObjectiveC++
+  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);
   ParseDeclarator(DeclaratorInfo);
index ef208290533bd25f9b56000853579e9208db6df9..3ab8be7c2857f46cb4b27f3570e8d32211d84855 100644 (file)
@@ -192,6 +192,9 @@ private:
   virtual void ObjCActOnStartOfMethodDef(Scope *S, DeclTy *D);
   
   virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtTy *Body);
+  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace,
+                                  SourceLocation RBrace, const char *Lang,
+                                  unsigned StrSize, DeclTy *D);
   
   /// Scope actions.
   virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
index cbcd79ea4f8c0f01e56a0a1e9c6b7340459da1e1..1610008191b0889c31f50dea0cc6301ffcc5d3ca 100644 (file)
@@ -1615,6 +1615,27 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
   Enum->defineElements(EltList, BestType);
 }
 
+Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc,
+                                    SourceLocation LBrace,
+                                    SourceLocation RBrace,
+                                    const char *Lang,
+                                    unsigned StrSize,
+                                    DeclTy *D) {
+  LinkageSpecDecl::LanguageIDs Language;
+  Decl *dcl = static_cast<Decl *>(D);
+  if (strncmp(Lang, "\"C\"", StrSize) == 0)
+    Language = LinkageSpecDecl::lang_c;
+  else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
+    Language = LinkageSpecDecl::lang_cxx;
+  else {
+    Diag(Loc, diag::err_bad_language);
+    return 0;
+  }
+
+  // FIXME: Add all the various semantics of linkage specifications
+  return new LinkageSpecDecl(Loc, Language, dcl);
+}
+
 void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) {
   const char *attrName = rawAttr->getAttributeName()->getName();
   unsigned attrLen = rawAttr->getAttributeName()->getLength();
index 321eb4b70ca42cbb57eec17de65a10c21ae9c223..40af7bada0bd8d26fcc23fd980271e8511d137cf 100644 (file)
@@ -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,42 @@ protected:
   friend Decl* Decl::Create(llvm::Deserializer& D);
 };
 
+
+/// LinkageSpecDecl - This represents a linkage specification.  For example:
+///   extern "C" void foo();
+///
+class LinkageSpecDecl : public Decl {
+public:
+  /// LanguageIDs - Used to represent the language in a linkage
+  /// specification.  The values are part of the serialization abi for
+  /// ASTs and cannot be changed without altering that abi.  To help
+  /// ensure a stable abi for this, we choose the DW_LANG_ encodings
+  /// from the dwarf standard.
+  enum LanguageIDs { lang_c = /* DW_LANG_C */ 0x0002,
+                    lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 };
+private:
+  /// Language - The language for this linkage specification.
+  LanguageIDs Language;
+  /// D - This is the Decl of the linkage specification.
+  Decl *D;
+public:
+  LinkageSpecDecl(SourceLocation L, LanguageIDs lang, Decl *d)
+   : Decl(LinkageSpec, L), Language(lang), D(d) {}
+  
+  LanguageIDs getLanguage() const { return Language; }
+  const Decl *getDecl() const { return D; }
+  Decl *getDecl() { 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 1191455d743cb9eb0a62924983f6f9ec764bf69d..b91c7313f18766e62b7fdb2859b5fe795b2129d3 100644 (file)
@@ -537,6 +537,8 @@ DIAG(err_invalid_reference_qualifier_application, ERROR,
      "'%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 7fddcadae14ff4f8caacceb6e0de9a14bbad923a..b27e3d35f535a473b37b3fa0d55b3ab32b15fc02 100644 (file)
@@ -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);
index 8b4a0c1bfd4b245b4722b7a03885012c2e7e2a3a..0e5ae2a79baf5e55445d793e7ddd7df717f231b0 100644 (file)
@@ -154,6 +154,12 @@ public:
   virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
     return 0;
   }
+
+  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace,
+                                  SourceLocation RBrace, const char *Lang,
+                                  unsigned StrSize, DeclTy *D) {
+    return 0;
+  }
   
   //===--------------------------------------------------------------------===//
   // Type Parsing Callbacks.
index c1069c25f65fc674400c630d5bda004f62c8e9f2..508dc306ad259510ef5be511c5a70c9fcf86cff0 100644 (file)
@@ -437,6 +437,7 @@ private:
   // C++ 7: Declarations [dcl.dcl]
   
   DeclTy *ParseNamespace(unsigned Context);
+  DeclTy *ParseLinkage(unsigned Context);
 
 };