[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