Push DeclGroup much farther throughout the compiler. Now the various
productions (except the already broken ObjC cases like @class X,Y;) in
the parser that can produce more than one Decl return a DeclGroup instead
of a Decl, etc.
This allows elimination of the Decl::NextDeclarator field, and exposes
various clients that should look at all decls in a group, but which were
only looking at one (such as the dumper, printer, etc). These have been
fixed.
Still TODO:
1) there are some FIXME's in the code about potentially using
DeclGroup for better location info.
2) ParseObjCAtDirectives should return a DeclGroup due to @class etc.
3) I'm not sure what is going on with StmtIterator.cpp, or if it can
be radically simplified now.
4) I put a truly horrible hack in ParseTemplate.cpp.
I plan to bring up #3/4 on the mailing list, but don't plan to tackle
#1/2 in the short term.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68002 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 70daebf..cafeecb 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -16,7 +16,7 @@
namespace clang {
class ASTContext;
- class Decl;
+ class DeclGroupRef;
class TagDecl;
class HandleTagDeclDefinition;
@@ -25,7 +25,7 @@
/// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
class ASTConsumer {
public:
- virtual ~ASTConsumer();
+ virtual ~ASTConsumer() {}
/// Initialize - This is called to initialize the consumer, providing the
/// ASTContext.
@@ -35,7 +35,7 @@
/// called by the parser to process every top-level Decl*. Note that D can
/// be the head of a chain of Decls (e.g. for `int a, b` the chain will have
/// two elements). Use Decl::getNextDeclarator() to walk the chain.
- virtual void HandleTopLevelDecl(Decl *D) {}
+ virtual void HandleTopLevelDecl(DeclGroupRef D);
/// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed.
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index aaec16e..abdb10d 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -100,16 +100,9 @@
};
private:
- /// NextDeclarator - If this decl was part of a multi-declarator declaration,
- /// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
- Decl *NextDeclarator;
-
/// NextDeclInContext - The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is
/// traversed via DeclContext's decls_begin()/decls_end().
- /// FIXME: If NextDeclarator is non-NULL, will it always be the same
- /// as NextDeclInContext? If so, we can use a
- /// PointerIntPair<Decl*, 1> to make Decl smaller.
Decl *NextDeclInContext;
friend class DeclContext;
@@ -176,8 +169,7 @@
friend class CXXClassMemberWrapper;
Decl(Kind DK, DeclContext *DC, SourceLocation L)
- : NextDeclarator(0), NextDeclInContext(0),
- DeclCtx(DC),
+ : NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
@@ -276,13 +268,6 @@
void setLexicalDeclContext(DeclContext *DC);
- /// getNextDeclarator - If this decl was part of a multi-declarator
- /// declaration, such as "int X, Y, *Z;" this returns the decl for the next
- /// declarator. Otherwise it returns null.
- Decl *getNextDeclarator() { return NextDeclarator; }
- const Decl *getNextDeclarator() const { return NextDeclarator; }
- void setNextDeclarator(Decl *N) { NextDeclarator = N; }
-
// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
// scoped decl is defined outside the current function or method. This is
// roughly global variables and functions, but also handles enums (which could
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index b1c2575..1a85463 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -34,7 +34,7 @@
DeclGroup(unsigned numdecls, Decl** decls);
public:
- static DeclGroup* Create(ASTContext& C, unsigned numdecls, Decl** decls);
+ static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
void Destroy(ASTContext& C);
unsigned size() const { return NumDecls; }
@@ -57,6 +57,8 @@
};
class DeclGroupRef {
+ // Note this is not a PointerIntPair because we need the address of the
+ // non-group case to be valid as a Decl** for iteration.
enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
Decl* D;
@@ -71,6 +73,14 @@
explicit DeclGroupRef(DeclGroup* dg)
: D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
+ static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+ if (NumDecls == 0)
+ return DeclGroupRef();
+ if (NumDecls == 1)
+ return DeclGroupRef(Decls[0]);
+ return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
+ }
+
typedef Decl** iterator;
typedef Decl* const * const_iterator;
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 84023d6..a58fc81 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -71,6 +71,7 @@
typedef ActionBase::ExprTy ExprTy;
typedef ActionBase::StmtTy StmtTy;
typedef OpaquePtr<0> DeclPtrTy;
+ typedef OpaquePtr<1> DeclGroupPtrTy;
typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<1>.
typedef void AttrTy;
typedef void BaseTy;
@@ -130,6 +131,13 @@
// Declaration Tracking Callbacks.
//===--------------------------------------------------------------------===//
+ /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it
+ /// needs a decl group, it calls this to convert between the two
+ /// representations.
+ virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
+ return DeclGroupPtrTy();
+ }
+
/// getTypeName - Return non-null if the specified identifier is a type name
/// in the current scope.
/// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
@@ -210,11 +218,7 @@
/// 'Init' specifies the initializer if any. This is for things like:
/// "int X = 4" or "typedef int foo".
///
- /// LastInGroup is non-null for cases where one declspec has multiple
- /// declarators on it. For example in 'int A, B', ActOnDeclarator will be
- /// called with LastInGroup=A when invoked for B.
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D,
- DeclPtrTy LastInGroup) {
+ virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
return DeclPtrTy();
}
@@ -253,10 +257,12 @@
/// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
/// gives the actions implementation a chance to process the group as a whole.
- virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group) {
- return Group;
+ virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
+ unsigned NumDecls) {
+ return DeclGroupPtrTy();
}
+
/// @brief Indicates that all K&R-style parameter declarations have
/// been parsed prior to a function definition.
/// @param S The function prototype scope.
@@ -270,7 +276,7 @@
virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
// Default to ActOnDeclarator.
return ActOnStartOfFunctionDef(FnBodyScope,
- ActOnDeclarator(FnBodyScope, D,DeclPtrTy()));
+ ActOnDeclarator(FnBodyScope, D));
}
/// ActOnStartOfFunctionDef - This is called at the start of a function
@@ -415,7 +421,8 @@
bool isStmtExpr) {
return StmtEmpty();
}
- virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl,SourceLocation StartLoc,
+ virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+ SourceLocation StartLoc,
SourceLocation EndLoc) {
return StmtEmpty();
}
@@ -1041,8 +1048,7 @@
virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
Declarator &D,
ExprTy *BitfieldWidth,
- ExprTy *Init,
- DeclPtrTy LastInGroup) {
+ ExprTy *Init) {
return DeclPtrTy();
}
@@ -1408,9 +1414,8 @@
unsigned allNum = 0,
DeclPtrTy *allProperties = 0,
unsigned pNum = 0,
- DeclPtrTy *allTUVars = 0,
+ DeclGroupPtrTy *allTUVars = 0,
unsigned tuvNum = 0) {
- return;
}
// ActOnProperty - called to build one property AST
virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
@@ -1570,8 +1575,7 @@
/// ActOnDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D,
- DeclPtrTy LastInGroup);
+ virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D);
/// ActOnPopScope - When a scope is popped, if any typedefs are now
/// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 66058ca..eb82057 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -120,6 +120,7 @@
typedef Action::ExprTy ExprTy;
typedef Action::StmtTy StmtTy;
typedef Action::DeclPtrTy DeclPtrTy;
+ typedef Action::DeclGroupPtrTy DeclGroupPtrTy;
typedef Action::TypeTy TypeTy;
typedef Action::BaseTy BaseTy;
typedef Action::MemInitTy MemInitTy;
@@ -167,7 +168,7 @@
/// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
/// the EOF was encountered.
- bool ParseTopLevelDecl(DeclPtrTy &Result);
+ bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
private:
//===--------------------------------------------------------------------===//
@@ -547,8 +548,8 @@
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
- DeclPtrTy ParseExternalDeclaration();
- DeclPtrTy ParseDeclarationOrFunctionDefinition(
+ DeclGroupPtrTy ParseExternalDeclaration();
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
TemplateParameterLists *TemplateParams = 0,
AccessSpecifier AS = AS_none);
@@ -807,9 +808,9 @@
//===--------------------------------------------------------------------===//
// C99 6.7: Declarations.
- DeclPtrTy ParseDeclaration(unsigned Context);
- DeclPtrTy ParseSimpleDeclaration(unsigned Context);
- DeclPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
+ DeclGroupPtrTy ParseDeclaration(unsigned Context);
+ DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context);
+ DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
void ParseDeclarationSpecifiers(DeclSpec &DS,
TemplateParameterLists *TemplateParams = 0,
@@ -1009,7 +1010,7 @@
AccessSpecifier AS = AS_none);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
DeclPtrTy TagDecl);
- DeclPtrTy ParseCXXClassMemberDeclaration(AccessSpecifier AS);
+ void ParseCXXClassMemberDeclaration(AccessSpecifier AS);
void ParseConstructorInitializer(DeclPtrTy ConstructorDecl);
MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl);
diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp
index 6c44d1a..f37cbde 100644
--- a/lib/AST/ASTConsumer.cpp
+++ b/lib/AST/ASTConsumer.cpp
@@ -12,7 +12,8 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
using namespace clang;
-ASTConsumer::~ASTConsumer() {}
+void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {}
+
diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp
index 36a7c2b..64b0399 100644
--- a/lib/AST/DeclGroup.cpp
+++ b/lib/AST/DeclGroup.cpp
@@ -19,13 +19,12 @@
#include "llvm/Bitcode/Deserialize.h"
using namespace clang;
-DeclGroup* DeclGroup::Create(ASTContext& C, unsigned numdecls, Decl** decls) {
- assert (numdecls > 0);
- unsigned size = sizeof(DeclGroup) + sizeof(Decl*) * numdecls;
- unsigned alignment = llvm::AlignOf<DeclGroup>::Alignment;
- void* mem = C.Allocate(size, alignment);
- new (mem) DeclGroup(numdecls, decls);
- return static_cast<DeclGroup*>(mem);
+DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+ assert(NumDecls > 1 && "Invalid DeclGroup");
+ unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
+ void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
+ new (Mem) DeclGroup(NumDecls, Decls);
+ return static_cast<DeclGroup*>(Mem);
}
/// Emit - Serialize a DeclGroup to Bitcode.
@@ -37,9 +36,9 @@
/// Read - Deserialize a DeclGroup from Bitcode.
DeclGroup* DeclGroup::Read(llvm::Deserializer& D, ASTContext& C) {
unsigned NumDecls = (unsigned) D.ReadInt();
- unsigned size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
+ unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
unsigned alignment = llvm::AlignOf<DeclGroup>::Alignment;
- DeclGroup* DG = (DeclGroup*) C.Allocate(size, alignment);
+ DeclGroup* DG = (DeclGroup*) C.Allocate(Size, alignment);
new (DG) DeclGroup();
DG->NumDecls = NumDecls;
D.BatchReadOwnedPtrs(NumDecls, &(*DG)[0], C);
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 8e3ef08..acaced2 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -39,7 +39,6 @@
S.EmitInt(Access);
S.EmitPtr(cast_or_null<Decl>(getDeclContext())); // From Decl.
S.EmitPtr(cast_or_null<Decl>(getLexicalDeclContext())); // From Decl.
- S.EmitPtr(NextDeclarator);
if (const DeclContext *DC = dyn_cast<const DeclContext>(this))
DC->EmitOutRec(S);
@@ -144,7 +143,6 @@
D.ReadPtr(MDC->SemanticDC, SemaDCPtrID);
D.ReadPtr(MDC->LexicalDC, LexicalDCPtrID);
}
- D.ReadPtr(Dcl->NextDeclarator);
if (DeclContext *DC = dyn_cast<DeclContext>(Dcl))
DC->ReadOutRec(D, C);
bool OwnsNext = D.ReadBool();
diff --git a/lib/AST/StmtIterator.cpp b/lib/AST/StmtIterator.cpp
index 94829c0..20024f5 100644
--- a/lib/AST/StmtIterator.cpp
+++ b/lib/AST/StmtIterator.cpp
@@ -67,12 +67,11 @@
if (inDecl()) {
assert (decl);
+ // FIXME: SIMPLIFY AWAY.
if (ImmediateAdvance)
- decl = decl->getNextDeclarator();
-
- for ( ; decl ; decl = decl->getNextDeclarator())
- if (HandleDecl(decl))
- return;
+ decl = 0;
+ else if (HandleDecl(decl))
+ return;
}
else {
assert (inDeclGroup());
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index d41f133..896464e 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -60,16 +60,16 @@
*M, *TD, Diags));
}
- virtual void HandleTopLevelDecl(Decl *D) {
+ virtual void HandleTopLevelDecl(DeclGroupRef DG) {
// Make sure to emit all elements of a Decl.
- for (; D; D = D->getNextDeclarator())
- Builder->EmitTopLevelDecl(D);
+ for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+ Builder->EmitTopLevelDecl(*I);
}
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
- /// (e.g. struct, union, enum, class) is completed. This allows the client to
- /// hack on the type, which can occur at any point in the file (because these
- /// can be defined in declspecs).
+ /// to (e.g. struct, union, enum, class) is completed. This allows the
+ /// client hack on the type, which can occur at any point in the file
+ /// (because these can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {
Builder->UpdateCompletedType(D);
}
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 049228f..f31aef6 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -144,7 +144,7 @@
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
Action::DeclPtrTy
-MinimalAction::ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy LastInGroup) {
+MinimalAction::ActOnDeclarator(Scope *S, Declarator &D) {
IdentifierInfo *II = D.getIdentifier();
// If there is no identifier associated with this declarator, bail out.
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index e139cf9..45eaa74 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -27,8 +27,7 @@
assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) &&
"Current token not a '{' or ':'!");
- DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0,
- DeclPtrTy());
+ DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0);
// Consume the tokens and store them for later parsing.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 5a8b2b8..1f8522f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -228,27 +228,36 @@
/// [C++0x] static_assert-declaration
/// others... [FIXME]
///
-Parser::DeclPtrTy Parser::ParseDeclaration(unsigned Context) {
+Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context) {
+ DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
case tok::kw_export:
case tok::kw_template:
- return ParseTemplateDeclarationOrSpecialization(Context);
+ SingleDecl = ParseTemplateDeclarationOrSpecialization(Context);
+ break;
case tok::kw_namespace:
- return ParseNamespace(Context);
+ SingleDecl = ParseNamespace(Context);
+ break;
case tok::kw_using:
- return ParseUsingDirectiveOrDeclaration(Context);
+ SingleDecl = ParseUsingDirectiveOrDeclaration(Context);
+ break;
case tok::kw_static_assert:
- return ParseStaticAssertDeclaration();
+ SingleDecl = ParseStaticAssertDeclaration();
+ break;
default:
return ParseSimpleDeclaration(Context);
}
+
+ // This routine returns a DeclGroup, if the thing we parsed only contains a
+ // single decl, convert it now.
+ return Actions.ConvertDeclToDeclGroup(SingleDecl);
}
/// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
/// declaration-specifiers init-declarator-list[opt] ';'
///[C90/C++]init-declarator-list ';' [TODO]
/// [OMP] threadprivate-directive [TODO]
-Parser::DeclPtrTy Parser::ParseSimpleDeclaration(unsigned Context) {
+Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context) {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
@@ -257,7 +266,8 @@
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
ConsumeToken();
- return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
}
Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
@@ -291,12 +301,11 @@
/// According to the standard grammar, =default and =delete are function
/// definitions, but that definitely doesn't fit with the parser here.
///
-Parser::DeclPtrTy Parser::
+Parser::DeclGroupPtrTy Parser::
ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
-
- // Declarators may be grouped together ("int X, *Y, Z();"). Provide info so
- // that they can be chained properly if the actions want this.
- Parser::DeclPtrTy LastDeclInGroup;
+ // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls
+ // that we parse together here.
+ llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
// At this point, we know that it is not a function definition. Parse the
// rest of the init-declarator-list.
@@ -307,7 +316,7 @@
OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
if (AsmLabel.isInvalid()) {
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
D.setAsmLabel(AsmLabel.release());
@@ -322,21 +331,22 @@
}
// Inform the current actions module that we just parsed this declarator.
- LastDeclInGroup = Actions.ActOnDeclarator(CurScope, D, LastDeclInGroup);
+ DeclPtrTy ThisDecl = Actions.ActOnDeclarator(CurScope, D);
+ DeclsInGroup.push_back(ThisDecl);
// Parse declarator '=' initializer.
if (Tok.is(tok::equal)) {
ConsumeToken();
if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
SourceLocation DelLoc = ConsumeToken();
- Actions.SetDeclDeleted(LastDeclInGroup, DelLoc);
+ Actions.SetDeclDeleted(ThisDecl, DelLoc);
} else {
OwningExprResult Init(ParseInitializer());
if (Init.isInvalid()) {
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
- Actions.AddInitializerToDecl(LastDeclInGroup, move(Init));
+ Actions.AddInitializerToDecl(ThisDecl, move(Init));
}
} else if (Tok.is(tok::l_paren)) {
// Parse C++ direct initializer: '(' expression-list ')'
@@ -355,12 +365,12 @@
if (!InvalidExpr) {
assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
"Unexpected number of commas!");
- Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc,
+ Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
move_arg(Exprs),
&CommaLocs[0], RParenLoc);
}
} else {
- Actions.ActOnUninitializedDecl(LastDeclInGroup);
+ Actions.ActOnUninitializedDecl(ThisDecl);
}
// If we don't have a comma, it is either the end of the list (a ';') or an
@@ -395,23 +405,26 @@
// for(is key; in keys) is error.
if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) {
Diag(Tok, diag::err_parse_error);
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
- return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
+
+ return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
+ DeclsInGroup.size());
}
// If this is an ObjC2 for-each loop, this is a successful declarator
// parse. The syntax for these looks like:
// 'for' '(' declaration 'in' expr ')' statement
if (D.getContext() == Declarator::ForContext && isTokIdentifier_in())
- return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
+ return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
+ DeclsInGroup.size());
Diag(Tok, diag::err_parse_error);
// Skip to end of block or statement
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
ConsumeToken();
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
/// ParseSpecifierQualifierList
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index c50a033..37a460c 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -663,14 +663,17 @@
/// constant-initializer:
/// '=' constant-expression
///
-Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
+void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
// static_assert-declaration
- if (Tok.is(tok::kw_static_assert))
- return ParseStaticAssertDeclaration();
+ if (Tok.is(tok::kw_static_assert)) {
+ ParseStaticAssertDeclaration();
+ return;
+ }
- if (Tok.is(tok::kw_template))
- return ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext,
- AS);
+ if (Tok.is(tok::kw_template)) {
+ ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, AS);
+ return;
+ }
// Handle: member-declaration ::= '__extension__' member-declaration
if (Tok.is(tok::kw___extension__)) {
@@ -692,14 +695,15 @@
// class-specifier or an enum-specifier or in a friend declaration.
// FIXME: Friend declarations.
switch (DS.getTypeSpecType()) {
- case DeclSpec::TST_struct:
- case DeclSpec::TST_union:
- case DeclSpec::TST_class:
- case DeclSpec::TST_enum:
- return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
- default:
- Diag(DSStart, diag::err_no_declarators);
- return DeclPtrTy();
+ case DeclSpec::TST_struct:
+ case DeclSpec::TST_union:
+ case DeclSpec::TST_class:
+ case DeclSpec::TST_enum:
+ Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ return;
+ default:
+ Diag(DSStart, diag::err_no_declarators);
+ return;
}
}
@@ -714,7 +718,7 @@
SkipUntil(tok::r_brace, true);
if (Tok.is(tok::semi))
ConsumeToken();
- return DeclPtrTy();
+ return;
}
// function-definition:
@@ -724,7 +728,7 @@
Diag(Tok, diag::err_func_def_no_params);
ConsumeBrace();
SkipUntil(tok::r_brace, true);
- return DeclPtrTy();
+ return;
}
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
@@ -734,10 +738,11 @@
// assumes the declarator represents a function, not a typedef.
ConsumeBrace();
SkipUntil(tok::r_brace, true);
- return DeclPtrTy();
+ return;
}
- return ParseCXXInlineMethodDef(AS, DeclaratorInfo);
+ ParseCXXInlineMethodDef(AS, DeclaratorInfo);
+ return;
}
}
@@ -745,7 +750,7 @@
// member-declarator
// member-declarator-list ',' member-declarator
- DeclPtrTy LastDeclInGroup;
+ llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
OwningExprResult BitfieldSize(Actions);
OwningExprResult Init(Actions);
@@ -784,14 +789,14 @@
}
// NOTE: If Sema is the Action module and declarator is an instance field,
- // this call will *not* return the created decl; LastDeclInGroup will be
- // returned instead.
+ // this call will *not* return the created decl; It will return null.
// See Sema::ActOnCXXMemberDeclarator for details.
- LastDeclInGroup = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
- DeclaratorInfo,
- BitfieldSize.release(),
- Init.release(),
- LastDeclInGroup);
+ DeclPtrTy ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
+ DeclaratorInfo,
+ BitfieldSize.release(),
+ Init.release());
+ if (ThisDecl)
+ DeclsInGroup.push_back(ThisDecl);
if (DeclaratorInfo.isFunctionDeclarator() &&
DeclaratorInfo.getDeclSpec().getStorageClassSpec()
@@ -807,7 +812,7 @@
// Push this method onto the stack of late-parsed method
// declarations.
getCurTopClassStack().MethodDecls.push_back(
- LateParsedMethodDeclaration(LastDeclInGroup));
+ LateParsedMethodDeclaration(ThisDecl));
LateMethod = &getCurTopClassStack().MethodDecls.back();
// Add all of the parameters prior to this one (they don't
@@ -853,8 +858,9 @@
if (Tok.is(tok::semi)) {
ConsumeToken();
- // Reverse the chain list.
- return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
+ Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
+ DeclsInGroup.size());
+ return;
}
Diag(Tok, diag::err_expected_semi_decl_list);
@@ -862,7 +868,7 @@
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
ConsumeToken();
- return DeclPtrTy();
+ return;
}
/// ParseCXXMemberSpecification - Parse the class definition.
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 8ff1944..05c919c 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -215,7 +215,7 @@
tok::ObjCKeywordKind contextKey) {
llvm::SmallVector<DeclPtrTy, 32> allMethods;
llvm::SmallVector<DeclPtrTy, 16> allProperties;
- llvm::SmallVector<DeclPtrTy, 8> allTUVariables;
+ llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables;
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
SourceLocation AtEndLoc;
@@ -253,8 +253,7 @@
// FIXME: as the name implies, this rule allows function definitions.
// We could pass a flag or check for functions during semantic analysis.
- DeclPtrTy VFDecl = ParseDeclarationOrFunctionDefinition();
- allTUVariables.push_back(VFDecl);
+ allTUVariables.push_back(ParseDeclarationOrFunctionDefinition());
continue;
}
@@ -359,13 +358,9 @@
// Insert collected methods declarations into the @interface object.
// This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
Actions.ActOnAtEnd(AtEndLoc, interfaceDecl,
- allMethods.empty() ? 0 : &allMethods[0],
- allMethods.size(),
- allProperties.empty() ? 0 : &allProperties[0],
- allProperties.size(),
- allTUVariables.empty() ? 0 :
- &allTUVariables[0],
- allTUVariables.size());
+ &allMethods[0], allMethods.size(),
+ &allProperties[0], allProperties.size(),
+ &allTUVariables[0], allTUVariables.size());
}
/// Parse property attribute declarations.
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index b996c74..b1a32de 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -101,7 +101,7 @@
default: {
if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation();
- DeclPtrTy Decl = ParseDeclaration(Declarator::BlockContext);
+ DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext);
// FIXME: Pass in the right location for the end of the declstmt.
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclStart);
}
@@ -444,7 +444,7 @@
if (isDeclarationStatement()) {
// FIXME: Save the __extension__ on the decl as a node somehow.
SourceLocation DeclStart = Tok.getLocation();
- DeclPtrTy Res = ParseDeclaration(Declarator::BlockContext);
+ DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext);
// FIXME: Pass in the right location for the end of the declstmt.
R = Actions.ActOnDeclStmt(Res, DeclStart, DeclStart);
} else {
@@ -912,10 +912,9 @@
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
SourceLocation DeclStart = Tok.getLocation();
- DeclPtrTy aBlockVarDecl = ParseSimpleDeclaration(Declarator::ForContext);
+ DeclGroupPtrTy VarDecls = ParseSimpleDeclaration(Declarator::ForContext);
// FIXME: Pass in the right location for the end of the declstmt.
- FirstPart = Actions.ActOnDeclStmt(aBlockVarDecl, DeclStart,
- DeclStart);
+ FirstPart = Actions.ActOnDeclStmt(VarDecls, DeclStart, DeclStart);
if ((ForEach = isTokIdentifier_in())) {
ConsumeToken(); // consume 'in'
SecondPart = ParseExpression();
@@ -929,12 +928,10 @@
if (Tok.is(tok::semi)) {
ConsumeToken();
- }
- else if ((ForEach = isTokIdentifier_in())) {
+ } else if ((ForEach = isTokIdentifier_in())) {
ConsumeToken(); // consume 'in'
SecondPart = ParseExpression();
- }
- else {
+ } else {
if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
SkipUntil(tok::semi);
}
@@ -995,11 +992,11 @@
return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
move(SecondPart), move(ThirdPart),
RParenLoc, move(Body));
- else
- return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
- move(FirstPart),
- move(SecondPart),
- RParenLoc, move(Body));
+
+ return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
+ move(FirstPart),
+ move(SecondPart),
+ RParenLoc, move(Body));
}
/// ParseGotoStatement
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 29b8a14..b962cbf 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -94,7 +94,12 @@
} while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
// Parse the actual template declaration.
- return ParseDeclarationOrFunctionDefinition(&ParamLists, AS);
+
+ // FIXME: This accepts template<typename x> int y;
+ // FIXME: Converting DeclGroupPtr to DeclPtr like this is an insanely gruesome
+ // hack, will bring up on cfe-dev.
+ DeclGroupPtrTy DG = ParseDeclarationOrFunctionDefinition(&ParamLists, AS);
+ return DeclPtrTy::make(DG.get());
}
/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 00a3349..56f922d 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -324,8 +324,8 @@
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
/// action tells us to. This returns true if the EOF was encountered.
-bool Parser::ParseTopLevelDecl(DeclPtrTy &Result) {
- Result = DeclPtrTy();
+bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
+ Result = DeclGroupPtrTy();
if (Tok.is(tok::eof)) {
Actions.ActOnEndOfTranslationUnit();
return true;
@@ -342,7 +342,7 @@
void Parser::ParseTranslationUnit() {
Initialize();
- DeclPtrTy Res;
+ DeclGroupPtrTy Res;
while (!ParseTopLevelDecl(Res))
/*parse them all*/;
@@ -368,20 +368,21 @@
/// [GNU] asm-definition:
/// simple-asm-expr ';'
///
-Parser::DeclPtrTy Parser::ParseExternalDeclaration() {
+Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
+ DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
case tok::semi:
Diag(Tok, diag::ext_top_level_semi);
ConsumeToken();
// TODO: Invoke action for top-level semicolon.
- return DeclPtrTy();
+ return DeclGroupPtrTy();
case tok::r_brace:
Diag(Tok, diag::err_expected_external_declaration);
ConsumeBrace();
- return DeclPtrTy();
+ return DeclGroupPtrTy();
case tok::eof:
Diag(Tok, diag::err_expected_external_declaration);
- return DeclPtrTy();
+ return DeclGroupPtrTy();
case tok::kw___extension__: {
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
@@ -394,20 +395,26 @@
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
"top-level asm block");
- if (!Result.isInvalid())
- return Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result));
- return DeclPtrTy();
+ if (Result.isInvalid())
+ return DeclGroupPtrTy();
+ SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result));
+ break;
}
case tok::at:
- // @ is not a legal token unless objc is enabled, no need to check.
- return ParseObjCAtDirectives();
+ // @ is not a legal token unless objc is enabled, no need to check for ObjC.
+ /// FIXME: ParseObjCAtDirectives should return a DeclGroup for things like
+ /// @class foo, bar;
+ SingleDecl = ParseObjCAtDirectives();
+ break;
case tok::minus:
case tok::plus:
- if (getLang().ObjC1)
- return ParseObjCMethodDefinition();
- Diag(Tok, diag::err_expected_external_declaration);
- ConsumeToken();
- return DeclPtrTy();
+ if (!getLang().ObjC1) {
+ Diag(Tok, diag::err_expected_external_declaration);
+ ConsumeToken();
+ return DeclGroupPtrTy();
+ }
+ SingleDecl = ParseObjCMethodDefinition();
+ break;
case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
@@ -420,6 +427,10 @@
// We can't tell whether this is a function-definition or declaration yet.
return ParseDeclarationOrFunctionDefinition();
}
+
+ // This routine returns a DeclGroup, if the thing we parsed only contains a
+ // single decl, convert it now.
+ return Actions.ConvertDeclToDeclGroup(SingleDecl);
}
/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
@@ -438,7 +449,7 @@
/// [!C99] init-declarator-list ';' [TODO: warn in c99 mode]
/// [OMP] threadprivate-directive [TODO]
///
-Parser::DeclPtrTy
+Parser::DeclGroupPtrTy
Parser::ParseDeclarationOrFunctionDefinition(
TemplateParameterLists *TemplateParams,
AccessSpecifier AS) {
@@ -450,7 +461,8 @@
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
ConsumeToken();
- return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
}
// ObjC2 allows prefix attributes on class interfaces and protocols.
@@ -462,14 +474,18 @@
!Tok.isObjCAtKeyword(tok::objc_protocol)) {
Diag(Tok, diag::err_objc_unexpected_attr);
SkipUntil(tok::semi); // FIXME: better skip?
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
const char *PrevSpec = 0;
if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec))
Diag(AtLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
+
+ DeclPtrTy TheDecl;
if (Tok.isObjCAtKeyword(tok::objc_protocol))
- return ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
- return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
+ TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
+ else
+ TheDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
}
// If the declspec consisted only of 'extern' and we have a string
@@ -477,8 +493,10 @@
// 'extern "C"'.
if (Tok.is(tok::string_literal) && getLang().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
- DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier)
- return ParseLinkage(Declarator::FileContext);
+ DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
+ DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ }
// Parse the first declarator.
Declarator DeclaratorInfo(DS, Declarator::FileContext);
@@ -489,7 +507,7 @@
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
ConsumeToken();
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
// If the declarator is the start of a function definition, handle it.
@@ -500,8 +518,12 @@
Tok.is(tok::kw___attribute) || // int X() __attr__ -> not a function def
(getLang().CPlusPlus &&
Tok.is(tok::l_paren)) ) { // int X(0) -> not a function def [C++]
- // FALL THROUGH.
- } else if (DeclaratorInfo.isFunctionDeclarator() &&
+ // Parse the init-declarator-list for a normal declaration.
+ return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+ }
+
+
+ if (DeclaratorInfo.isFunctionDeclarator() &&
(Tok.is(tok::l_brace) || // int X() {}
(!getLang().CPlusPlus &&
isDeclarationSpecifier()) || // int X(f) int f; {}
@@ -519,20 +541,18 @@
} else {
SkipUntil(tok::semi);
}
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
- return ParseFunctionDefinition(DeclaratorInfo);
- } else {
- if (DeclaratorInfo.isFunctionDeclarator())
- Diag(Tok, diag::err_expected_fn_body);
- else
- Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
- SkipUntil(tok::semi);
- return DeclPtrTy();
+ DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
}
-
- // Parse the init-declarator-list for a normal declaration.
- return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+
+ if (DeclaratorInfo.isFunctionDeclarator())
+ Diag(Tok, diag::err_expected_fn_body);
+ else
+ Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
+ SkipUntil(tok::semi);
+ return DeclGroupPtrTy();
}
/// ParseFunctionDefinition - We parsed and verified that the specified
diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp
index 59a04da..4bcb478 100644
--- a/lib/Sema/ParseAST.cpp
+++ b/lib/Sema/ParseAST.cpp
@@ -44,16 +44,14 @@
Consumer->Initialize(Ctx);
- Parser::DeclPtrTy ADecl;
+ Parser::DeclGroupPtrTy ADecl;
while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file.
// If we got a null return and something *was* parsed, ignore it. This
// is due to a top-level semicolon, an action override, or a parse error
// skipping something.
- if (ADecl) {
- Decl *D = ADecl.getAs<Decl>();
- Consumer->HandleTopLevelDecl(D);
- }
+ if (ADecl)
+ Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
};
Consumer->HandleTranslationUnit(Ctx);
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0ebccf3..b7903c1 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -328,29 +328,28 @@
/// an empty string if not. This is used for pretty crash reporting.
virtual std::string getDeclName(DeclPtrTy D);
+ DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr);
+
virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, const CXXScopeSpec *SS);
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D,
- DeclPtrTy LastInGroup){
- return ActOnDeclarator(S, D, LastInGroup, false);
+ virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
+ return ActOnDeclarator(S, D, false);
}
- DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy LastInGroup,
- bool IsFunctionDefinition);
+ DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition);
void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
Scope *S);
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, Decl* LastDeclarator,
+ QualType R,
Decl* PrevDecl, bool& InvalidDecl,
bool &Redeclaration);
NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, Decl* LastDeclarator,
+ QualType R,
NamedDecl* PrevDecl, bool& InvalidDecl,
bool &Redeclaration);
bool CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
bool &Redeclaration);
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, Decl *LastDeclarator,
- NamedDecl* PrevDecl,
+ QualType R, NamedDecl* PrevDecl,
bool IsFunctionDefinition,
bool& InvalidDecl, bool &Redeclaration);
bool CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
@@ -367,8 +366,8 @@
void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit);
void ActOnUninitializedDecl(DeclPtrTy dcl);
virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc);
- virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group);
-
+ virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
+ unsigned NumDecls);
virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D);
virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, Declarator &D);
virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, DeclPtrTy D);
@@ -490,8 +489,7 @@
Stmt* ParentCompoundStmt);
/// Subroutines of ActOnDeclarator().
- TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
- Decl *LastDecl);
+ TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T);
bool MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
@@ -1084,7 +1082,7 @@
virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
MultiStmtArg Elts,
bool isStmtExpr);
- virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl,
+ virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
SourceLocation StartLoc,
SourceLocation EndLoc);
virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal,
@@ -1589,8 +1587,7 @@
virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
Declarator &D,
ExprTy *BitfieldWidth,
- ExprTy *Init,
- DeclPtrTy LastInGroup);
+ ExprTy *Init);
virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD,
Scope *S,
@@ -2076,7 +2073,7 @@
virtual void ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
DeclPtrTy *allMethods = 0, unsigned allNum = 0,
DeclPtrTy *allProperties = 0, unsigned pNum = 0,
- DeclPtrTy *allTUVars = 0, unsigned tuvNum = 0);
+ DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
FieldDeclarator &FD, ObjCDeclSpec &ODS,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f98da95..be9a0e2 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -39,6 +39,10 @@
return "";
}
+Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
+ return DeclGroupPtrTy::make(DeclGroupRef(Ptr.getAs<Decl>()));
+}
+
/// \brief If the identifier refers to a type name within this scope,
/// return the declaration of that type.
///
@@ -1235,10 +1239,7 @@
}
Sema::DeclPtrTy
-Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy lastDecl,
- bool IsFunctionDefinition) {
- NamedDecl *LastDeclarator =
- dyn_cast_or_null<NamedDecl>(lastDecl.getAs<Decl>());
+Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
DeclarationName Name = GetNameForDeclarator(D);
// All of these full declarators require an identifier. If it doesn't have
@@ -1356,14 +1357,14 @@
bool Redeclaration = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
- New = ActOnTypedefDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
+ New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl,
InvalidDecl, Redeclaration);
} else if (R->isFunctionType()) {
- New = ActOnFunctionDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
+ New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl,
IsFunctionDefinition, InvalidDecl,
Redeclaration);
} else {
- New = ActOnVariableDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
+ New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl,
InvalidDecl, Redeclaration);
}
@@ -1454,8 +1455,7 @@
NamedDecl*
Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, Decl* LastDeclarator,
- Decl* PrevDecl, bool& InvalidDecl,
+ QualType R, Decl* PrevDecl, bool& InvalidDecl,
bool &Redeclaration) {
// Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
if (D.getCXXScopeSpec().isSet()) {
@@ -1475,7 +1475,7 @@
diag::err_virtual_non_function);
}
- TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, LastDeclarator);
+ TypedefDecl *NewTD = ParseTypedefDecl(S, D, R);
if (!NewTD) return 0;
// Handle attributes prior to checking for duplicates in MergeVarDecl
@@ -1580,8 +1580,7 @@
NamedDecl*
Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, Decl* LastDeclarator,
- NamedDecl* PrevDecl, bool& InvalidDecl,
+ QualType R,NamedDecl* PrevDecl, bool& InvalidDecl,
bool &Redeclaration) {
DeclarationName Name = GetNameForDeclarator(D);
@@ -1645,7 +1644,6 @@
// FIXME: Move to DeclGroup...
D.getDeclSpec().getSourceRange().getBegin());
NewVD->setThreadSpecified(ThreadSpecified);
- NewVD->setNextDeclarator(LastDeclarator);
// Set the lexical context. If the declarator has a C++ scope specifier, the
// lexical context will be different from the semantic context.
@@ -1800,8 +1798,8 @@
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, Decl *LastDeclarator,
- NamedDecl* PrevDecl, bool IsFunctionDefinition,
+ QualType R, NamedDecl* PrevDecl,
+ bool IsFunctionDefinition,
bool& InvalidDecl, bool &Redeclaration) {
assert(R.getTypePtr()->isFunctionType());
@@ -1937,7 +1935,6 @@
// FIXME: Move to DeclGroup...
D.getDeclSpec().getSourceRange().getBegin());
}
- NewFD->setNextDeclarator(LastDeclarator);
// Set the lexical context. If the declarator has a C++
// scope specifier, the lexical context will be different
@@ -2517,39 +2514,29 @@
}
}
-/// The declarators are chained together backwards, reverse the list.
-Sema::DeclPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, DeclPtrTy group) {
- // Often we have single declarators, handle them quickly.
- Decl *Group = group.getAs<Decl>();
- if (Group == 0)
- return DeclPtrTy();
+Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
+ unsigned NumDecls) {
+ llvm::SmallVector<Decl*, 8> Decls;
- Decl *NewGroup = 0;
- if (Group->getNextDeclarator() == 0)
- NewGroup = Group;
- else { // reverse the list.
- while (Group) {
- Decl *Next = Group->getNextDeclarator();
- Group->setNextDeclarator(NewGroup);
- NewGroup = Group;
- Group = Next;
- }
- }
+ for (unsigned i = 0; i != NumDecls; ++i)
+ if (Decl *D = Group[i].getAs<Decl>())
+ Decls.push_back(D);
+
// Perform semantic analysis that depends on having fully processed both
// the declarator and initializer.
- for (Decl *ID = NewGroup; ID; ID = ID->getNextDeclarator()) {
- VarDecl *IDecl = dyn_cast<VarDecl>(ID);
+ for (unsigned i = 0, e = Decls.size(); i != e; ++i) {
+ VarDecl *IDecl = dyn_cast<VarDecl>(Decls[i]);
if (!IDecl)
continue;
QualType T = IDecl->getType();
-
+
// Block scope. C99 6.7p7: If an identifier for an object is declared with
// no linkage (C99 6.2.2p6), the type for the object shall be complete...
if (IDecl->isBlockVarDecl() &&
IDecl->getStorageClass() != VarDecl::Extern) {
if (!IDecl->isInvalidDecl() &&
RequireCompleteType(IDecl->getLocation(), T,
- diag::err_typecheck_decl_incomplete_type))
+ diag::err_typecheck_decl_incomplete_type))
IDecl->setInvalidDecl();
}
// File scope. C99 6.9.2p2: A declaration of an identifier for and
@@ -2560,13 +2547,13 @@
if (IDecl->isTentativeDefinition(Context)) {
QualType CheckType = T;
unsigned DiagID = diag::err_typecheck_decl_incomplete_type;
-
+
const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(T);
if (ArrayT) {
CheckType = ArrayT->getElementType();
DiagID = diag::err_illegal_decl_array_incomplete_type;
}
-
+
if (IDecl->isInvalidDecl()) {
// Do nothing with invalid declarations
} else if ((ArrayT || IDecl->getStorageClass() == VarDecl::Static) &&
@@ -2578,9 +2565,11 @@
}
}
}
- return DeclPtrTy::make(NewGroup);
+ return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
+ &Decls[0], NumDecls));
}
+
/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
/// to introduce parameters into function prototype scope.
Sema::DeclPtrTy
@@ -2722,9 +2711,8 @@
Scope *ParentScope = FnBodyScope->getParent();
- return ActOnStartOfFunctionDef(FnBodyScope,
- ActOnDeclarator(ParentScope, D, DeclPtrTy(),
- /*IsFunctionDefinition=*/true));
+ DeclPtrTy DP = ActOnDeclarator(ParentScope, D, /*IsFunctionDefinition=*/true);
+ return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
@@ -3056,8 +3044,7 @@
}
}
-TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
- Decl *LastDeclarator) {
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) {
assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
@@ -3076,7 +3063,6 @@
TD->setTypedefForAnonDecl(NewTD);
}
- NewTD->setNextDeclarator(LastDeclarator);
if (D.getInvalidType())
NewTD->setInvalidDecl();
return NewTD;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 258641f..ea2af68 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -473,8 +473,7 @@
/// declarators on it.
Sema::DeclPtrTy
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
- ExprTy *BW, ExprTy *InitExpr,
- DeclPtrTy LastInGroup) {
+ ExprTy *BW, ExprTy *InitExpr) {
const DeclSpec &DS = D.getDeclSpec();
DeclarationName Name = GetNameForDeclarator(D);
Expr *BitWidth = static_cast<Expr*>(BW);
@@ -553,10 +552,10 @@
AS);
assert(Member && "HandleField never returns null");
} else {
- Member = ActOnDeclarator(S, D, LastInGroup).getAs<Decl>();
+ Member = ActOnDeclarator(S, D).getAs<Decl>();
if (!Member) {
if (BitWidth) DeleteExpr(BitWidth);
- return LastInGroup;
+ return DeclPtrTy();
}
// Non-instance-fields can't have a bitfield.
@@ -595,7 +594,7 @@
if (isInstField) {
FieldCollector->Add(cast<FieldDecl>(Member));
- return LastInGroup;
+ return DeclPtrTy();
}
return DeclPtrTy::make(Member);
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index d84a0d1..18e3e4f 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1234,8 +1234,7 @@
void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
DeclPtrTy *allMethods, unsigned allNum,
DeclPtrTy *allProperties, unsigned pNum,
- DeclPtrTy *allTUVars,
- unsigned tuvNum) {
+ DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
Decl *ClassDecl = classDecl.getAs<Decl>();
// FIXME: If we don't have a ClassDecl, we have an error. We should consider
@@ -1339,16 +1338,18 @@
}
}
}
- if (isInterfaceDeclKind)
- for (unsigned i = 0; i < tuvNum; i++) {
- if (VarDecl *VDecl = dyn_cast<VarDecl>(allTUVars[i].getAs<Decl>())) {
- if (VDecl->getStorageClass() != VarDecl::Extern &&
- VDecl->getStorageClass() != VarDecl::PrivateExtern) {
- NamedDecl *ClassNameDecl = dyn_cast<NamedDecl>(ClassDecl);
- Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass)
- << ClassNameDecl->getIdentifier();
+ if (isInterfaceDeclKind) {
+ // Reject invalid vardecls.
+ for (unsigned i = 0; i != tuvNum; i++) {
+ DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
+ for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+ if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {
+ if (VDecl->getStorageClass() != VarDecl::Extern &&
+ VDecl->getStorageClass() != VarDecl::PrivateExtern)
+ Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass)
+ << cast<NamedDecl>(ClassDecl)->getIdentifier();
}
- }
+ }
}
}
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index b331911..d258ec3 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -37,31 +37,13 @@
return Owned(new (Context) NullStmt(SemiLoc));
}
-Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclPtrTy decl,
+Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- Decl *D = decl.getAs<Decl>();
- if (D == 0)
- return StmtError();
-
- // This is a temporary hack until we are always passing around
- // DeclGroupRefs.
- llvm::SmallVector<Decl*, 10> decls;
- while (D) {
- Decl* d = D;
- D = D->getNextDeclarator();
- d->setNextDeclarator(0);
- decls.push_back(d);
- }
-
- assert (!decls.empty());
-
- if (decls.size() == 1) {
- DeclGroupRef DG(*decls.begin());
- return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc));
- }
-
- DeclGroupRef DG(DeclGroup::Create(Context, decls.size(), &decls[0]));
+ // If we have an invalid decl, just return an error.
+ if (!dg) return StmtError();
+
+ DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc));
}
diff --git a/tools/clang-cc/ASTConsumers.cpp b/tools/clang-cc/ASTConsumers.cpp
index cb09659..3910c77 100644
--- a/tools/clang-cc/ASTConsumers.cpp
+++ b/tools/clang-cc/ASTConsumers.cpp
@@ -539,8 +539,9 @@
public:
ASTPrinter(llvm::raw_ostream* o = NULL) : DeclPrinter(o) {}
- virtual void HandleTopLevelDecl(Decl *D) {
- PrintDecl(D);
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ PrintDecl(*I);
}
};
} // end anonymous namespace
@@ -562,11 +563,15 @@
SM = &Context.getSourceManager();
}
- virtual void HandleTopLevelDecl(Decl *D);
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
+ void HandleTopLevelSingleDecl(Decl *D);
};
} // end anonymous namespace
-void ASTDumper::HandleTopLevelDecl(Decl *D) {
+void ASTDumper::HandleTopLevelSingleDecl(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
PrintFunctionDeclStart(FD);
@@ -624,12 +629,17 @@
void Initialize(ASTContext &Context) {
SM = &Context.getSourceManager();
}
+
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
- virtual void HandleTopLevelDecl(Decl *D);
+ void HandleTopLevelSingleDecl(Decl *D);
};
}
-void ASTViewer::HandleTopLevelDecl(Decl *D) {
+void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
DeclPrinter().PrintFunctionDeclStart(FD);
diff --git a/tools/clang-cc/AnalysisConsumer.cpp b/tools/clang-cc/AnalysisConsumer.cpp
index 366f384..bc38593 100644
--- a/tools/clang-cc/AnalysisConsumer.cpp
+++ b/tools/clang-cc/AnalysisConsumer.cpp
@@ -220,7 +220,12 @@
Ctx = &Context;
}
- virtual void HandleTopLevelDecl(Decl *D);
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
+
+ void HandleTopLevelSingleDecl(Decl *D);
virtual void HandleTranslationUnit(ASTContext &C);
void HandleCode(Decl* D, Stmt* Body, Actions& actions);
@@ -411,7 +416,7 @@
// AnalysisConsumer implementation.
//===----------------------------------------------------------------------===//
-void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
+void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
switch (D->getKind()) {
case Decl::Function: {
FunctionDecl* FD = cast<FunctionDecl>(D);
diff --git a/tools/clang-cc/Backend.cpp b/tools/clang-cc/Backend.cpp
index 0faabbe..3b3be31 100644
--- a/tools/clang-cc/Backend.cpp
+++ b/tools/clang-cc/Backend.cpp
@@ -8,11 +8,12 @@
//===----------------------------------------------------------------------===//
#include "ASTConsumers.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompileOptions.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
@@ -117,13 +118,14 @@
LLVMIRGeneration.stopTimer();
}
- virtual void HandleTopLevelDecl(Decl *D) {
- PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
Context->getSourceManager(),
"LLVM IR generation of declaration");
+
if (CompileOpts.TimePasses)
LLVMIRGeneration.startTimer();
-
+
Gen->HandleTopLevelDecl(D);
if (CompileOpts.TimePasses)
diff --git a/tools/clang-cc/PrintParserCallbacks.cpp b/tools/clang-cc/PrintParserCallbacks.cpp
index 9dce6d8..dc25f54 100644
--- a/tools/clang-cc/PrintParserCallbacks.cpp
+++ b/tools/clang-cc/PrintParserCallbacks.cpp
@@ -29,8 +29,7 @@
/// ActOnDeclarator - This callback is invoked when a declarator is parsed
/// and 'Init' specifies the initializer if any. This is for things like:
/// "int X = 4" or "typedef int foo".
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D,
- DeclPtrTy LastInGroup) {
+ virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
llvm::cout << __FUNCTION__ << " ";
if (IdentifierInfo *II = D.getIdentifier()) {
llvm::cout << "'" << II->getName() << "'";
@@ -40,7 +39,7 @@
llvm::cout << "\n";
// Pass up to EmptyActions so that the symbol table is maintained right.
- return MinimalAction::ActOnDeclarator(S, D, LastInGroup);
+ return MinimalAction::ActOnDeclarator(S, D);
}
/// ActOnPopScope - This callback is called immediately before the specified
/// scope is popped and deleted.
@@ -112,17 +111,20 @@
llvm::cout << __FUNCTION__ << "\n";
}
- /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
- /// gives the actions implementation a chance to process the group as a whole.
- virtual DeclPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy Group) {
+ /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed,
+ /// this gives the actions implementation a chance to process the group as
+ /// a whole.
+ virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, DeclPtrTy *Group,
+ unsigned NumDecls) {
llvm::cout << __FUNCTION__ << "\n";
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
/// ActOnStartOfFunctionDef - This is called at the start of a function
/// definition, instead of calling ActOnDeclarator. The Declarator includes
/// information about formal arguments that are part of this function.
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
+ virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope,
+ Declarator &D){
llvm::cout << __FUNCTION__ << "\n";
return DeclPtrTy();
}
@@ -256,7 +258,7 @@
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
- virtual OwningStmtResult ActOnDeclStmt(DeclPtrTy Decl,
+ virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
SourceLocation StartLoc,
SourceLocation EndLoc) {
llvm::cout << __FUNCTION__ << "\n";
diff --git a/tools/clang-cc/RewriteBlocks.cpp b/tools/clang-cc/RewriteBlocks.cpp
index 2672d32..f302913 100644
--- a/tools/clang-cc/RewriteBlocks.cpp
+++ b/tools/clang-cc/RewriteBlocks.cpp
@@ -83,7 +83,11 @@
const char *NewStr, unsigned NewLength);
// Top Level Driver code.
- virtual void HandleTopLevelDecl(Decl *D);
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
+ void HandleTopLevelSingleDecl(Decl *D);
void HandleDeclInMainFile(Decl *D);
// Top level
@@ -336,7 +340,7 @@
// Top Level Driver Code
//===----------------------------------------------------------------------===//
-void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
+void RewriteBlocks::HandleTopLevelSingleDecl(Decl *D) {
// Two cases: either the decl could be in the main file, or it could be in a
// #included file. If the former, rewrite it now. If the later, check to see
// if we rewrote the #include/#import.
diff --git a/tools/clang-cc/RewriteObjC.cpp b/tools/clang-cc/RewriteObjC.cpp
index e0267ec..5fcecc6 100644
--- a/tools/clang-cc/RewriteObjC.cpp
+++ b/tools/clang-cc/RewriteObjC.cpp
@@ -126,7 +126,11 @@
virtual void Initialize(ASTContext &context);
// Top Level Driver code.
- virtual void HandleTopLevelDecl(Decl *D);
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
+ void HandleTopLevelSingleDecl(Decl *D);
void HandleDeclInMainFile(Decl *D);
RewriteObjC(std::string inFile, std::string outFile,
Diagnostic &D, const LangOptions &LOpts);
@@ -550,7 +554,7 @@
// Top Level Driver Code
//===----------------------------------------------------------------------===//
-void RewriteObjC::HandleTopLevelDecl(Decl *D) {
+void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
// Two cases: either the decl could be in the main file, or it could be in a
// #included file. If the former, rewrite it now. If the later, check to see
// if we rewrote the #include/#import.
@@ -583,7 +587,7 @@
for (DeclContext::decl_iterator DI = LSD->decls_begin(),
DIEnd = LSD->decls_end();
DI != DIEnd; ++DI)
- HandleTopLevelDecl(*DI);
+ HandleTopLevelSingleDecl(*DI);
}
// If we have a decl in the main file, see if we should rewrite it.
if (SM->isFromMainFile(Loc))
diff --git a/tools/clang-cc/SerializationTest.cpp b/tools/clang-cc/SerializationTest.cpp
index 74ccb4b..fda8d88 100644
--- a/tools/clang-cc/SerializationTest.cpp
+++ b/tools/clang-cc/SerializationTest.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/CFG.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
#include "clang.h"
#include "ASTConsumers.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -73,7 +74,7 @@
TranslationUnitDecl *TUD = Ctx.getTranslationUnitDecl();
for (DeclContext::decl_iterator I = TUD->decls_begin(), E =TUD->decls_end();
I != E; ++I)
- FilePrinter->HandleTopLevelDecl(*I);
+ FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I));
}
// Serialize the translation unit.
@@ -124,7 +125,7 @@
TranslationUnitDecl *TUD = NewCtx->getTranslationUnitDecl();
for (DeclContext::decl_iterator I = TUD->decls_begin(), E = TUD->decls_end();
I != E; ++I)
- FilePrinter->HandleTopLevelDecl(*I);
+ FilePrinter->HandleTopLevelDecl(DeclGroupRef(*I));
}
delete NewCtx;
diff --git a/tools/clang-cc/clang.cpp b/tools/clang-cc/clang.cpp
index c0a2ae7..5b1e6ab 100644
--- a/tools/clang-cc/clang.cpp
+++ b/tools/clang-cc/clang.cpp
@@ -37,6 +37,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
#include "clang/Parse/Parser.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
@@ -1563,7 +1564,7 @@
TranslationUnitDecl *TUD = Ctx->getTranslationUnitDecl();
for (DeclContext::decl_iterator I = TUD->decls_begin(), E = TUD->decls_end();
I != E; ++I)
- Consumer->HandleTopLevelDecl(*I);
+ Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
}