[cfe-commits] r156289 - in /cfe/trunk: include/clang/Parse/Parser.h include/clang/Sema/DelayedDiagnostic.h include/clang/Sema/Sema.h lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseTemplate.cpp lib/Parse/RAIIObjectsForParser.h lib/Sema/Sema.cpp lib/Sema/SemaDeclAttr.cpp
John McCall
rjmccall at apple.com
Sun May 6 23:16:42 PDT 2012
Author: rjmccall
Date: Mon May 7 01:16:41 2012
New Revision: 156289
URL: http://llvm.org/viewvc/llvm-project?rev=156289&view=rev
Log:
Refactor DelayedDiagnostics so that it keeps diagnostics in
separate pools owned by the RAII objects that keep pushing
decl state. This gives us quite a bit more flexibility.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/DelayedDiagnostic.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseObjc.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Parse/RAIIObjectsForParser.h
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon May 7 01:16:41 2012
@@ -31,6 +31,9 @@
class DeclGroupRef;
class DiagnosticBuilder;
class Parser;
+ class ParsingDeclRAIIObject;
+ class ParsingDeclSpec;
+ class ParsingDeclarator;
class PragmaUnusedHandler;
class ColonProtectionRAIIObject;
class InMessageExpressionRAIIObject;
@@ -207,6 +210,7 @@
const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
Preprocessor &getPreprocessor() const { return PP; }
Sema &getActions() const { return Actions; }
+ AttributeFactory &getAttrFactory() { return AttrFactory; }
const Token &getCurToken() const { return Tok; }
Scope *getCurScope() const { return Actions.getCurScope(); }
@@ -951,120 +955,7 @@
return *ClassStack.top();
}
- /// \brief RAII object used to inform the actions that we're
- /// currently parsing a declaration. This is active when parsing a
- /// variable's initializer, but not when parsing the body of a
- /// class or function definition.
- class ParsingDeclRAIIObject {
- Sema &Actions;
- Sema::ParsingDeclState State;
- bool Popped;
-
- public:
- ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
- push();
- }
-
- ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *Other)
- : Actions(P.Actions) {
- if (Other) steal(*Other);
- else push();
- }
-
- /// Creates a RAII object which steals the state from a different
- /// object instead of pushing.
- ParsingDeclRAIIObject(ParsingDeclRAIIObject &Other)
- : Actions(Other.Actions) {
- steal(Other);
- }
-
- ~ParsingDeclRAIIObject() {
- abort();
- }
-
- /// Resets the RAII object for a new declaration.
- void reset() {
- abort();
- push();
- }
-
- /// Signals that the context was completed without an appropriate
- /// declaration being parsed.
- void abort() {
- pop(0);
- }
-
- void complete(Decl *D) {
- assert(!Popped && "ParsingDeclaration has already been popped!");
- pop(D);
- }
-
- private:
- void steal(ParsingDeclRAIIObject &Other) {
- State = Other.State;
- Popped = Other.Popped;
- Other.Popped = true;
- }
-
- void push() {
- State = Actions.PushParsingDeclaration();
- Popped = false;
- }
-
- void pop(Decl *D) {
- if (!Popped) {
- Actions.PopParsingDeclaration(State, D);
- Popped = true;
- }
- }
- };
-
- /// A class for parsing a DeclSpec.
- class ParsingDeclSpec : public DeclSpec {
- ParsingDeclRAIIObject ParsingRAII;
-
- public:
- ParsingDeclSpec(Parser &P) : DeclSpec(P.AttrFactory), ParsingRAII(P) {}
- ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
- : DeclSpec(P.AttrFactory), ParsingRAII(P, RAII) {}
-
- void complete(Decl *D) {
- ParsingRAII.complete(D);
- }
-
- void abort() {
- ParsingRAII.abort();
- }
- };
-
- /// A class for parsing a declarator.
- class ParsingDeclarator : public Declarator {
- ParsingDeclRAIIObject ParsingRAII;
-
- public:
- ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
- : Declarator(DS, C), ParsingRAII(P) {
- }
-
- const ParsingDeclSpec &getDeclSpec() const {
- return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
- }
-
- ParsingDeclSpec &getMutableDeclSpec() const {
- return const_cast<ParsingDeclSpec&>(getDeclSpec());
- }
-
- void clear() {
- Declarator::clear();
- ParsingRAII.reset();
- }
-
- void complete(Decl *D) {
- ParsingRAII.complete(D);
- }
- };
-
- /// \brief RAII object used to
+ /// \brief RAII object used to manage the parsing of a class definition.
class ParsingClassDefinition {
Parser &P;
bool Popped;
Modified: cfe/trunk/include/clang/Sema/DelayedDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DelayedDiagnostic.h?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DelayedDiagnostic.h (original)
+++ cfe/trunk/include/clang/Sema/DelayedDiagnostic.h Mon May 7 01:16:41 2012
@@ -21,7 +21,7 @@
#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
#define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
-#include "clang/AST/DeclCXX.h"
+#include "clang/Sema/Sema.h"
namespace clang {
namespace sema {
@@ -214,7 +214,63 @@
};
};
+/// DelayedDiagnosticPool - A collection of diagnostics which were
+/// delayed.
+class DelayedDiagnosticPool {
+ const DelayedDiagnosticPool *Parent;
+ llvm::SmallVector<DelayedDiagnostic, 4> Diagnostics;
+
+ // Do not implement.
+ DelayedDiagnosticPool(const DelayedDiagnosticPool &other);
+ DelayedDiagnosticPool &operator=(const DelayedDiagnosticPool &other);
+public:
+ DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {}
+ ~DelayedDiagnosticPool() {
+ for (llvm::SmallVectorImpl<DelayedDiagnostic>::iterator
+ i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i)
+ i->Destroy();
+ }
+
+ const DelayedDiagnosticPool *getParent() const { return Parent; }
+
+ /// Does this pool, or any of its ancestors, contain any diagnostics?
+ bool empty() const {
+ return (Diagnostics.empty() && (Parent == NULL || Parent->empty()));
+ }
+
+ /// Add a diagnostic to this pool.
+ void add(const DelayedDiagnostic &diag) {
+ Diagnostics.push_back(diag);
+ }
+
+ /// Steal the diagnostics from the given pool.
+ void steal(DelayedDiagnosticPool &pool) {
+ if (pool.Diagnostics.empty()) return;
+
+ if (Diagnostics.empty()) {
+ Diagnostics = llvm_move(pool.Diagnostics);
+ } else {
+ Diagnostics.append(pool.pool_begin(), pool.pool_end());
+ }
+ pool.Diagnostics.clear();
+ }
+
+ typedef llvm::SmallVectorImpl<DelayedDiagnostic>::const_iterator
+ pool_iterator;
+ pool_iterator pool_begin() const { return Diagnostics.begin(); }
+ pool_iterator pool_end() const { return Diagnostics.end(); }
+ bool pool_empty() const { return Diagnostics.empty(); }
+};
+
}
+
+/// Add a diagnostic to the current delay pool.
+inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) {
+ assert(shouldDelayDiagnostics() && "trying to delay without pool");
+ CurPool->add(diag);
+}
+
+
}
#endif
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon May 7 01:16:41 2012
@@ -169,6 +169,7 @@
class BlockScopeInfo;
class CompoundScopeInfo;
class DelayedDiagnostic;
+ class DelayedDiagnosticPool;
class FunctionScopeInfo;
class LambdaScopeInfo;
class PossiblyUnreachableDiag;
@@ -355,93 +356,63 @@
class DelayedDiagnostics;
- class ParsingDeclState {
- unsigned SavedStackSize;
- friend class Sema::DelayedDiagnostics;
- };
-
- class ProcessingContextState {
- unsigned SavedParsingDepth;
- unsigned SavedActiveStackBase;
+ class DelayedDiagnosticsState {
+ sema::DelayedDiagnosticPool *SavedPool;
friend class Sema::DelayedDiagnostics;
};
+ typedef DelayedDiagnosticsState ParsingDeclState;
+ typedef DelayedDiagnosticsState ProcessingContextState;
/// A class which encapsulates the logic for delaying diagnostics
/// during parsing and other processing.
class DelayedDiagnostics {
- /// \brief The stack of diagnostics that were delayed due to being
- /// produced during the parsing of a declaration.
- sema::DelayedDiagnostic *Stack;
-
- /// \brief The number of objects on the delayed-diagnostics stack.
- unsigned StackSize;
-
- /// \brief The current capacity of the delayed-diagnostics stack.
- unsigned StackCapacity;
-
- /// \brief The index of the first "active" delayed diagnostic in
- /// the stack. When parsing class definitions, we ignore active
- /// delayed diagnostics from the surrounding context.
- unsigned ActiveStackBase;
-
- /// \brief The depth of the declarations we're currently parsing.
- /// This gets saved and reset whenever we enter a class definition.
- unsigned ParsingDepth;
+ /// \brief The current pool of diagnostics into which delayed
+ /// diagnostics should go.
+ sema::DelayedDiagnosticPool *CurPool;
public:
- DelayedDiagnostics() : Stack(0), StackSize(0), StackCapacity(0),
- ActiveStackBase(0), ParsingDepth(0) {}
-
- ~DelayedDiagnostics() {
- delete[] reinterpret_cast<char*>(Stack);
- }
+ DelayedDiagnostics() : CurPool(0) {}
- /// Adds a delayed diagnostic.
- void add(const sema::DelayedDiagnostic &diag);
+ /// Adds a delayed diagnostic.
+ void add(const sema::DelayedDiagnostic &diag); // in DelayedDiagnostic.h
/// Determines whether diagnostics should be delayed.
- bool shouldDelayDiagnostics() { return ParsingDepth > 0; }
+ bool shouldDelayDiagnostics() { return CurPool != 0; }
- /// Observe that we've started parsing a declaration. Access and
- /// deprecation diagnostics will be delayed; when the declaration
- /// is completed, all active delayed diagnostics will be evaluated
- /// in its context, and then active diagnostics stack will be
- /// popped down to the saved depth.
- ParsingDeclState pushParsingDecl() {
- ParsingDepth++;
+ /// Returns the current delayed-diagnostics pool.
+ sema::DelayedDiagnosticPool *getCurrentPool() const {
+ return CurPool;
+ }
- ParsingDeclState state;
- state.SavedStackSize = StackSize;
+ /// Enter a new scope. Access and deprecation diagnostics will be
+ /// collected in this pool.
+ DelayedDiagnosticsState push(sema::DelayedDiagnosticPool &pool) {
+ DelayedDiagnosticsState state;
+ state.SavedPool = CurPool;
+ CurPool = &pool;
return state;
}
- /// Observe that we're completed parsing a declaration.
- static void popParsingDecl(Sema &S, ParsingDeclState state, Decl *decl);
-
- /// Observe that we've started processing a different context, the
- /// contents of which are semantically separate from the
- /// declarations it may lexically appear in. This sets aside the
- /// current stack of active diagnostics and starts afresh.
- ProcessingContextState pushContext() {
- assert(StackSize >= ActiveStackBase);
-
- ProcessingContextState state;
- state.SavedParsingDepth = ParsingDepth;
- state.SavedActiveStackBase = ActiveStackBase;
-
- ActiveStackBase = StackSize;
- ParsingDepth = 0;
+ /// Leave a delayed-diagnostic state that was previously pushed.
+ /// Do not emit any of the diagnostics. This is performed as part
+ /// of the bookkeeping of popping a pool "properly".
+ void popWithoutEmitting(DelayedDiagnosticsState state) {
+ CurPool = state.SavedPool;
+ }
+ /// Enter a new scope where access and deprecation diagnostics are
+ /// not delayed.
+ DelayedDiagnosticsState pushUndelayed() {
+ DelayedDiagnosticsState state;
+ state.SavedPool = CurPool;
+ CurPool = 0;
return state;
}
- /// Observe that we've stopped processing a context. This
- /// restores the previous stack of active diagnostics.
- void popContext(ProcessingContextState state) {
- assert(ActiveStackBase == StackSize);
- assert(ParsingDepth == 0);
- ActiveStackBase = state.SavedActiveStackBase;
- ParsingDepth = state.SavedParsingDepth;
+ /// Undo a previous pushUndelayed().
+ void popUndelayed(DelayedDiagnosticsState state) {
+ assert(CurPool == NULL);
+ CurPool = state.SavedPool;
}
} DelayedDiagnostics;
@@ -456,7 +427,7 @@
public:
ContextRAII(Sema &S, DeclContext *ContextToPush)
: S(S), SavedContext(S.CurContext),
- SavedContextState(S.DelayedDiagnostics.pushContext()),
+ SavedContextState(S.DelayedDiagnostics.pushUndelayed()),
SavedCXXThisTypeOverride(S.CXXThisTypeOverride)
{
assert(ContextToPush && "pushing null context");
@@ -466,7 +437,7 @@
void pop() {
if (!SavedContext) return;
S.CurContext = SavedContext;
- S.DelayedDiagnostics.popContext(SavedContextState);
+ S.DelayedDiagnostics.popUndelayed(SavedContextState);
S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
SavedContext = 0;
}
@@ -2608,19 +2579,17 @@
void DiagnoseEmptyLoopBody(const Stmt *S,
const Stmt *PossibleBody);
- ParsingDeclState PushParsingDeclaration() {
- return DelayedDiagnostics.pushParsingDecl();
- }
- void PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
- DelayedDiagnostics::popParsingDecl(*this, state, decl);
+ ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
+ return DelayedDiagnostics.push(pool);
}
+ void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
typedef ProcessingContextState ParsingClassState;
ParsingClassState PushParsingClass() {
- return DelayedDiagnostics.pushContext();
+ return DelayedDiagnostics.pushUndelayed();
}
void PopParsingClass(ParsingClassState state) {
- DelayedDiagnostics.popContext(state);
+ DelayedDiagnostics.popUndelayed(state);
}
void EmitDeprecationWarning(NamedDecl *D, StringRef Message,
Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Mon May 7 01:16:41 2012
@@ -16,6 +16,7 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Scope.h"
#include "clang/AST/DeclTemplate.h"
+#include "RAIIObjectsForParser.h"
using namespace clang;
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon May 7 01:16:41 2012
@@ -2560,7 +2560,7 @@
bool FirstDeclarator = true;
SourceLocation CommaLoc;
while (1) {
- ParsingDeclRAIIObject PD(*this);
+ ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
FieldDeclarator DeclaratorInfo(DS);
DeclaratorInfo.D.setCommaLoc(CommaLoc);
@@ -3067,7 +3067,7 @@
SourceLocation EqualLoc;
ExprResult AssignedVal;
- ParsingDeclRAIIObject PD(*this);
+ ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
if (Tok.is(tok::equal)) {
EqualLoc = ConsumeToken();
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Mon May 7 01:16:41 2012
@@ -965,7 +965,7 @@
tok::TokenKind mType,
tok::ObjCKeywordKind MethodImplKind,
bool MethodDefinition) {
- ParsingDeclRAIIObject PD(*this);
+ ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Mon May 7 01:16:41 2012
@@ -90,7 +90,8 @@
// Tell the action that names should be checked in the context of
// the declaration to come.
- ParsingDeclRAIIObject ParsingTemplateParams(*this);
+ ParsingDeclRAIIObject
+ ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);
// Parse multiple levels of template headers within this template
// parameter scope, e.g.,
@@ -213,10 +214,11 @@
return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
prefixAttrs);
- // Parse the declaration specifiers, stealing the accumulated
- // diagnostics from the template parameters.
+ // Parse the declaration specifiers, stealing any diagnostics from
+ // the template parameters.
ParsingDeclSpec DS(*this, &DiagsFromTParams);
+ // Move the attributes from the prefix into the DS.
DS.takeAttributesFrom(prefixAttrs);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
@@ -1132,7 +1134,8 @@
SourceLocation &DeclEnd,
AccessSpecifier AS) {
// This isn't really required here.
- ParsingDeclRAIIObject ParsingTemplateParams(*this);
+ ParsingDeclRAIIObject
+ ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);
return ParseSingleDeclarationAfterTemplate(Context,
ParsedTemplateInfo(ExternLoc,
Modified: cfe/trunk/lib/Parse/RAIIObjectsForParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/RAIIObjectsForParser.h?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/RAIIObjectsForParser.h (original)
+++ cfe/trunk/lib/Parse/RAIIObjectsForParser.h Mon May 7 01:16:41 2012
@@ -16,13 +16,156 @@
#define LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Sema.h"
namespace clang {
- // TODO: move ParsingDeclRAIIObject here.
// TODO: move ParsingClassDefinition here.
// TODO: move TentativeParsingAction here.
-
-
+
+ /// \brief RAII object used to inform the actions that we're
+ /// currently parsing a declaration. This is active when parsing a
+ /// variable's initializer, but not when parsing the body of a
+ /// class or function definition.
+ class ParsingDeclRAIIObject {
+ Sema &Actions;
+ sema::DelayedDiagnosticPool DiagnosticPool;
+ Sema::ParsingDeclState State;
+ bool Popped;
+
+ // Do not implement.
+ ParsingDeclRAIIObject(const ParsingDeclRAIIObject &other);
+ ParsingDeclRAIIObject &operator=(const ParsingDeclRAIIObject &other);
+
+ public:
+ enum NoParent_t { NoParent };
+ ParsingDeclRAIIObject(Parser &P, NoParent_t _)
+ : Actions(P.getActions()), DiagnosticPool(NULL) {
+ push();
+ }
+
+ /// Creates a RAII object whose pool is optionally parented by another.
+ ParsingDeclRAIIObject(Parser &P,
+ const sema::DelayedDiagnosticPool *parentPool)
+ : Actions(P.getActions()), DiagnosticPool(parentPool) {
+ push();
+ }
+
+ /// Creates a RAII object and, optionally, initialize its
+ /// diagnostics pool by stealing the diagnostics from another
+ /// RAII object (which is assumed to be the current top pool).
+ ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
+ : Actions(P.getActions()),
+ DiagnosticPool(other ? other->DiagnosticPool.getParent() : NULL) {
+ if (other) {
+ DiagnosticPool.steal(other->DiagnosticPool);
+ other->abort();
+ }
+ push();
+ }
+
+ ~ParsingDeclRAIIObject() {
+ abort();
+ }
+
+ sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
+ return DiagnosticPool;
+ }
+ const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
+ return DiagnosticPool;
+ }
+
+ /// Resets the RAII object for a new declaration.
+ void reset() {
+ abort();
+ push();
+ }
+
+ /// Signals that the context was completed without an appropriate
+ /// declaration being parsed.
+ void abort() {
+ pop(0);
+ }
+
+ void complete(Decl *D) {
+ assert(!Popped && "ParsingDeclaration has already been popped!");
+ pop(D);
+ }
+
+ private:
+ void steal(ParsingDeclRAIIObject &Other) {
+ DiagnosticPool.steal(Other.DiagnosticPool);
+ State = Other.State;
+ Popped = Other.Popped;
+ Other.Popped = true;
+ }
+
+ void push() {
+ State = Actions.PushParsingDeclaration(DiagnosticPool);
+ Popped = false;
+ }
+
+ void pop(Decl *D) {
+ if (!Popped) {
+ Actions.PopParsingDeclaration(State, D);
+ Popped = true;
+ }
+ }
+ };
+
+ /// A class for parsing a DeclSpec.
+ class ParsingDeclSpec : public DeclSpec {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingDeclSpec(Parser &P)
+ : DeclSpec(P.getAttrFactory()),
+ ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
+ ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
+ : DeclSpec(P.getAttrFactory()),
+ ParsingRAII(P, RAII) {}
+
+ const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
+ return ParsingRAII.getDelayedDiagnosticPool();
+ }
+
+ void complete(Decl *D) {
+ ParsingRAII.complete(D);
+ }
+
+ void abort() {
+ ParsingRAII.abort();
+ }
+ };
+
+ /// A class for parsing a declarator.
+ class ParsingDeclarator : public Declarator {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
+ : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
+ }
+
+ const ParsingDeclSpec &getDeclSpec() const {
+ return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
+ }
+
+ ParsingDeclSpec &getMutableDeclSpec() const {
+ return const_cast<ParsingDeclSpec&>(getDeclSpec());
+ }
+
+ void clear() {
+ Declarator::clear();
+ ParsingRAII.reset();
+ }
+
+ void complete(Decl *D) {
+ ParsingRAII.complete(D);
+ }
+ };
+
/// ExtensionRAIIObject - This saves the state of extension warnings when
/// constructed and disables them. When destructed, it restores them back to
/// the way they used to be. This is used to handle __extension__ in the
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon May 7 01:16:41 2012
@@ -18,6 +18,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/ExternalSemaSource.h"
@@ -201,7 +202,6 @@
ExternalSema->ForgetSema();
}
-
/// makeUnavailableInSystemHeader - There is an error in the current
/// context. If we're still in a system header, and we can plausibly
/// make the relevant declaration unavailable instead of erroring, do
@@ -426,6 +426,9 @@
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
+ assert(DelayedDiagnostics.getCurrentPool() == NULL
+ && "reached end of translation unit with a pool attached?");
+
// Only complete translation units define vtables and perform implicit
// instantiations.
if (TUKind == TU_Complete) {
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=156289&r1=156288&r2=156289&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon May 7 01:16:41 2012
@@ -4198,57 +4198,30 @@
diag.Triggered = true;
}
-// This duplicates a vector push_back but hides the need to know the
-// size of the type.
-void Sema::DelayedDiagnostics::add(const DelayedDiagnostic &diag) {
- assert(StackSize <= StackCapacity);
-
- // Grow the stack if necessary.
- if (StackSize == StackCapacity) {
- unsigned newCapacity = 2 * StackCapacity + 2;
- char *newBuffer = new char[newCapacity * sizeof(DelayedDiagnostic)];
- const char *oldBuffer = (const char*) Stack;
-
- if (StackCapacity)
- memcpy(newBuffer, oldBuffer, StackCapacity * sizeof(DelayedDiagnostic));
-
- delete[] oldBuffer;
- Stack = reinterpret_cast<sema::DelayedDiagnostic*>(newBuffer);
- StackCapacity = newCapacity;
- }
-
- assert(StackSize < StackCapacity);
- new (&Stack[StackSize++]) DelayedDiagnostic(diag);
-}
-
-void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state,
- Decl *decl) {
- DelayedDiagnostics &DD = S.DelayedDiagnostics;
-
- // Check the invariants.
- assert(DD.StackSize >= state.SavedStackSize);
- assert(state.SavedStackSize >= DD.ActiveStackBase);
- assert(DD.ParsingDepth > 0);
-
- // Drop the parsing depth.
- DD.ParsingDepth--;
-
- // If there are no active diagnostics, we're done.
- if (DD.StackSize == DD.ActiveStackBase)
- return;
-
- // We only want to actually emit delayed diagnostics when we
- // successfully parsed a decl.
- if (decl) {
- // We emit all the active diagnostics, not just those starting
- // from the saved state. The idea is this: we get one push for a
- // decl spec and another for each declarator; in a decl group like:
- // deprecated_typedef foo, *bar, baz();
- // only the declarator pops will be passed decls. This is correct;
- // we really do need to consider delayed diagnostics from the decl spec
- // for each of the different declarations.
- for (unsigned i = DD.ActiveStackBase, e = DD.StackSize; i != e; ++i) {
- DelayedDiagnostic &diag = DD.Stack[i];
+void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
+ assert(DelayedDiagnostics.getCurrentPool());
+ sema::DelayedDiagnosticPool &poppedPool =
+ *DelayedDiagnostics.getCurrentPool();
+ DelayedDiagnostics.popWithoutEmitting(state);
+
+ // When delaying diagnostics to run in the context of a parsed
+ // declaration, we only want to actually emit anything if parsing
+ // succeeds.
+ if (!decl) return;
+
+ // We emit all the active diagnostics in this pool or any of its
+ // parents. In general, we'll get one pool for the decl spec
+ // and a child pool for each declarator; in a decl group like:
+ // deprecated_typedef foo, *bar, baz();
+ // only the declarator pops will be passed decls. This is correct;
+ // we really do need to consider delayed diagnostics from the decl spec
+ // for each of the different declarations.
+ const sema::DelayedDiagnosticPool *pool = &poppedPool;
+ do {
+ for (sema::DelayedDiagnosticPool::pool_iterator
+ i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
+ // This const_cast is a bit lame. Really, Triggered should be mutable.
+ DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i);
if (diag.Triggered)
continue;
@@ -4256,25 +4229,19 @@
case DelayedDiagnostic::Deprecation:
// Don't bother giving deprecation diagnostics if the decl is invalid.
if (!decl->isInvalidDecl())
- S.HandleDelayedDeprecationCheck(diag, decl);
+ HandleDelayedDeprecationCheck(diag, decl);
break;
case DelayedDiagnostic::Access:
- S.HandleDelayedAccessCheck(diag, decl);
+ HandleDelayedAccessCheck(diag, decl);
break;
case DelayedDiagnostic::ForbiddenType:
- handleDelayedForbiddenType(S, diag, decl);
+ handleDelayedForbiddenType(*this, diag, decl);
break;
}
}
- }
-
- // Destroy all the delayed diagnostics we're about to pop off.
- for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i)
- DD.Stack[i].Destroy();
-
- DD.StackSize = state.SavedStackSize;
+ } while ((pool = pool->getParent()));
}
static bool isDeclDeprecated(Decl *D) {
More information about the cfe-commits
mailing list