[cfe-commits] r45904 - in /cfe/trunk: 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

Chris Lattner sabre at nondot.org
Fri Jan 11 23:05:38 PST 2008


Author: lattner
Date: Sat Jan 12 01:05:38 2008
New Revision: 45904

URL: http://llvm.org/viewvc/llvm-project?rev=45904&view=rev
Log:
Add first pieces of support for parsing and representing 
extern "C" in C++ mode.  Patch by Mike Stump!

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

Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Sat Jan 12 01:05:38 2008
@@ -37,6 +37,7 @@
 static unsigned nObjCCategoryImpl = 0;
 static unsigned nObjCCompatibleAlias = 0;
 static unsigned nObjCPropertyDecl = 0;
+static unsigned nLinkageSpecDecl = 0;
 
 static bool StatSwitch = false;
 
@@ -156,7 +157,9 @@
 	      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 @@
     case PropertyDecl:
       nObjCPropertyDecl++;
       break;
+    case LinkageSpec:
+      nLinkageSpecDecl++;
+      break;
   }
 }
 

Modified: cfe/trunk/AST/DeclSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/DeclSerialization.cpp?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/AST/DeclSerialization.cpp (original)
+++ cfe/trunk/AST/DeclSerialization.cpp Sat Jan 12 01:05:38 2008
@@ -422,3 +422,19 @@
 
   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);
+}

Modified: cfe/trunk/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.cpp?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenModule.cpp Sat Jan 12 01:05:38 2008
@@ -44,6 +44,16 @@
                     &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!

Modified: cfe/trunk/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.h?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/CodeGen/CodeGenModule.h Sat Jan 12 01:05:38 2008
@@ -95,6 +95,10 @@
   /// 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

Modified: cfe/trunk/CodeGen/ModuleBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/ModuleBuilder.cpp?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/CodeGen/ModuleBuilder.cpp Sat Jan 12 01:05:38 2008
@@ -13,6 +13,7 @@
 
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "CodeGenModule.h"
+#include "clang/AST/Decl.h"
 using namespace clang;
 
 
@@ -34,6 +35,16 @@
   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);

Modified: cfe/trunk/Driver/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.cpp?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/Driver/ASTConsumers.cpp (original)
+++ cfe/trunk/Driver/ASTConsumers.cpp Sat Jan 12 01:05:38 2008
@@ -39,6 +39,7 @@
     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 @@
     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 @@
   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 @@
         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.

Modified: cfe/trunk/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseDeclCXX.cpp?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/Parse/ParseDeclCXX.cpp Sat Jan 12 01:05:38 2008
@@ -80,3 +80,40 @@
   
   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);
+}

Modified: cfe/trunk/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/Parser.cpp?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/trunk/Parse/Parser.cpp Sat Jan 12 01:05:38 2008
@@ -386,6 +386,15 @@
     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);

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Sat Jan 12 01:05:38 2008
@@ -192,6 +192,9 @@
   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);

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Sat Jan 12 01:05:38 2008
@@ -1615,6 +1615,27 @@
   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();

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sat Jan 12 01:05:38 2008
@@ -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,42 @@
   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

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sat Jan 12 01:05:38 2008
@@ -537,6 +537,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,

Modified: cfe/trunk/include/clang/CodeGen/ModuleBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/ModuleBuilder.h?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/include/clang/CodeGen/ModuleBuilder.h (original)
+++ cfe/trunk/include/clang/CodeGen/ModuleBuilder.h Sat Jan 12 01:05:38 2008
@@ -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);

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sat Jan 12 01:05:38 2008
@@ -154,6 +154,12 @@
   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.

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=45904&r1=45903&r2=45904&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Jan 12 01:05:38 2008
@@ -437,6 +437,7 @@
   // C++ 7: Declarations [dcl.dcl]
   
   DeclTy *ParseNamespace(unsigned Context);
+  DeclTy *ParseLinkage(unsigned Context);
 
 };
 





More information about the cfe-commits mailing list