forked from OSchip/llvm-project
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:
parent
22ad7abdfe
commit
38376f1595
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -437,6 +437,7 @@ private:
|
|||
// C++ 7: Declarations [dcl.dcl]
|
||||
|
||||
DeclTy *ParseNamespace(unsigned Context);
|
||||
DeclTy *ParseLinkage(unsigned Context);
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue