Add first pieces of support for parsing and representing

extern "C" in C++ mode.  Patch by Mike Stump!

llvm-svn: 45904
This commit is contained in:
Chris Lattner 2008-01-12 07:05:38 +00:00
parent 22ad7abdfe
commit 38376f1595
15 changed files with 184 additions and 1 deletions

View 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;
}
}

View 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);
}

View 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!

View 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

View 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);

View 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.

View 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);
}

View 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);

View 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);

View 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();

View 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

View 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,

View 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);

View 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.

View File

@ -437,6 +437,7 @@ private:
// C++ 7: Declarations [dcl.dcl]
DeclTy *ParseNamespace(unsigned Context);
DeclTy *ParseLinkage(unsigned Context);
};