From: Douglas Gregor Date: Tue, 16 Dec 2008 22:23:02 +0000 (+0000) Subject: Make linkage-specifications hold on to all of their declarations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f44515a49b549171dc3ee9faa6281b72609da563;p=clang Make linkage-specifications hold on to all of their declarations git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61110 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index cc41642f94..4ff8d3cac2 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -185,9 +185,19 @@ void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) { "unknown language in linkage specification"); l = "C++"; } - Out << "extern \"" << l << "\" { "; - PrintDecl(LS->getDecl()); - Out << "}\n"; + + Out << "extern \"" << l << "\" "; + if (LS->hasBraces()) + Out << "{\n"; + + for (LinkageSpecDecl::decl_const_iterator D = LS->decls_begin(), + DEnd = LS->decls_end(); + D != DEnd; ++D) + PrintDecl(*D); + + if (LS->hasBraces()) + Out << "}"; + Out << "\n"; } void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) { diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index a28d8374e3..0e9c5287c4 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -894,18 +894,46 @@ public: private: /// Language - The language for this linkage specification. LanguageIDs Language; - /// D - This is the Decl of the linkage specification. - Decl *D; - + + /// HadBraces - Whether this linkage specification had curly braces or not. + bool HadBraces : 1; + + /// Decls - The declarations that were parsed as part of this + /// linkage specification. If HadBraces is false, this is a + /// Decl*. Otherwise, it's a Decl**. + void *Decls; + + /// NumDecls - The number of declarations stored in this linkage + /// specification. + unsigned NumDecls : 31; + LinkageSpecDecl(SourceLocation L, LanguageIDs lang, Decl *d) - : Decl(LinkageSpec, L), Language(lang), D(d) {} + : Decl(LinkageSpec, L), Language(lang), HadBraces(false), + Decls(d), NumDecls(1) {} + + LinkageSpecDecl(SourceLocation L, LanguageIDs lang, + Decl **InDecls, unsigned InNumDecls); + public: + ~LinkageSpecDecl(); + static LinkageSpecDecl *Create(ASTContext &C, SourceLocation L, LanguageIDs Lang, Decl *D); + + static LinkageSpecDecl *Create(ASTContext &C, SourceLocation L, + LanguageIDs Lang, + Decl **Decls, unsigned NumDecls); LanguageIDs getLanguage() const { return Language; } - const Decl *getDecl() const { return D; } - Decl *getDecl() { return D; } + + /// hasBraces - Determines whether this linkage specification had + /// braces in its syntactic form. + bool hasBraces() const { return HadBraces; } + + typedef Decl** decl_iterator; + typedef Decl** decl_const_iterator; + decl_const_iterator decls_begin() const; + decl_const_iterator decls_end() const; static bool classof(const Decl *D) { return D->getKind() == LinkageSpec; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 2bd2e4b22f..a0d8d085d8 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -240,8 +240,21 @@ public: return 0; } + /// ActOnLinkageSpec - Parsed a C++ linkage-specification that + /// contained braces. Lang/StrSize contains the language string that + /// was parsed at location Loc. Decls/NumDecls provides the + /// declarations parsed inside the linkage specification. virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace, SourceLocation RBrace, const char *Lang, + unsigned StrSize, + DeclTy **Decls, unsigned NumDecls) { + return 0; + } + + /// ActOnLinkageSpec - Parsed a C++ linkage-specification without + /// braces. Lang/StrSize contains the language string that was + /// parsed at location Loc. D is the declaration parsed. + virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang, unsigned StrSize, DeclTy *D) { return 0; } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index cce824609d..3faf5ac0c7 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -285,6 +285,21 @@ OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, return new (Mem) OverloadedFunctionDecl(DC, N); } +LinkageSpecDecl::LinkageSpecDecl(SourceLocation L, LanguageIDs lang, + Decl **InDecls, unsigned InNumDecls) + : Decl(LinkageSpec, L), Language(lang), HadBraces(true), + Decls(0), NumDecls(InNumDecls) { + Decl **NewDecls = new Decl*[NumDecls]; + for (unsigned I = 0; I < NumDecls; ++I) + NewDecls[I] = InDecls[I]; + Decls = NewDecls; +} + +LinkageSpecDecl::~LinkageSpecDecl() { + if (HadBraces) + delete [] (Decl**)Decls; +} + LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, SourceLocation L, LanguageIDs Lang, Decl *D) { @@ -292,3 +307,20 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, return new (Mem) LinkageSpecDecl(L, Lang, D); } +LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, + SourceLocation L, + LanguageIDs Lang, + Decl **Decls, unsigned NumDecls) { + void *Mem = C.getAllocator().Allocate(); + return new (Mem) LinkageSpecDecl(L, Lang, Decls, NumDecls); +} + +LinkageSpecDecl::decl_const_iterator LinkageSpecDecl::decls_begin() const { + if (hasBraces()) return (Decl**)Decls; + else return (Decl**)&Decls; +} + +LinkageSpecDecl::decl_iterator LinkageSpecDecl::decls_end() const { + if (hasBraces()) return (Decl**)Decls + NumDecls; + else return (Decl**)&Decls + 1; +} diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index c0ffb0c423..c853b1b84c 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -660,13 +660,30 @@ TemplateTypeParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { void LinkageSpecDecl::EmitInRec(Serializer& S) const { Decl::EmitInRec(S); S.EmitInt(getLanguage()); - S.EmitPtr(D); + S.EmitBool(HadBraces); + if (HadBraces) { + S.EmitInt(NumDecls); + for (decl_const_iterator D = decls_begin(), DEnd = decls_end(); + D != DEnd; ++D) + S.EmitPtr(*D); + } else { + S.EmitPtr((Decl*)Decls); + } } void LinkageSpecDecl::ReadInRec(Deserializer& D, ASTContext& C) { Decl::ReadInRec(D, C); Language = static_cast(D.ReadInt()); - D.ReadPtr(this->D); + HadBraces = D.ReadBool(); + if (HadBraces) { + NumDecls = D.ReadInt(); + Decl **NewDecls = new Decl*[NumDecls]; + Decls = NewDecls; + for (unsigned I = 0; I < NumDecls; ++I) + D.ReadPtr(NewDecls[I]); + } else { + D.ReadPtr(this->Decls); + } } //===----------------------------------------------------------------------===// diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 377186713e..ec2a37a852 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -108,24 +108,26 @@ Parser::DeclTy *Parser::ParseLinkage(unsigned Context) { SourceLocation Loc = ConsumeStringToken(); DeclTy *D = 0; - SourceLocation LBrace, RBrace; if (Tok.isNot(tok::l_brace)) { D = ParseDeclarationOrFunctionDefinition(); - } 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 Actions.ActOnLinkageSpec(Loc, LangBufPtr, StrSize, D); - if (!D) return 0; + } + + SourceLocation LBrace = ConsumeBrace(); + llvm::SmallVector InnerDecls; + while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + D = ParseExternalDeclaration(); + if (D) + InnerDecls.push_back(D); + } - return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, D); + SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); + return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, + &InnerDecls.front(), InnerDecls.size()); } /// ParseClassName - Parse a C++ class-name, which names a class. Note diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3e4228071c..89d9ebb583 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -288,6 +288,9 @@ public: virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtArg Body); virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace, SourceLocation RBrace, const char *Lang, + unsigned StrSize, + DeclTy **Decls, unsigned NumDecls); + virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang, unsigned StrSize, DeclTy *D); virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 81a4abea7f..b7c83162d6 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3382,11 +3382,34 @@ Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, return FileScopeAsmDecl::Create(Context, Loc, AsmString); } + /// ActOnLinkageSpec - Parsed a C++ linkage-specification that + /// contained braces. Lang/StrSize contains the language string that + /// was parsed at location Loc. Decls/NumDecls provides the + /// declarations parsed inside the linkage specification. Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace, SourceLocation RBrace, const char *Lang, unsigned StrSize, + DeclTy **Decls, unsigned NumDecls) { + LinkageSpecDecl::LanguageIDs Language; + 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 LinkageSpecDecl::Create(Context, Loc, Language, + (Decl **)Decls, NumDecls); +} + +Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc, + const char *Lang, unsigned StrSize, DeclTy *D) { LinkageSpecDecl::LanguageIDs Language; Decl *dcl = static_cast(D);