diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-07-09 16:54:53 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-07-09 16:54:53 +0000 |
commit | 94f29f4bf5d6b49dd1b7fc16cfa1521adc0c71c0 (patch) | |
tree | 2ace396d6886f3b5b0f6611c21e625c763a78770 /include/clang/Parse/Parser.h | |
parent | ee158bc29bc12ce544996f7cdfde14aba63acf4d (diff) |
Better parser recovery in Objective-C containers.
Previously it was possible to get an infinite-loop-on-invalid with a namespace
decl within @interface. Since 'namespace' is normally a safe place to retry
top-level parsing, we just didn't consume the token.
This adds a flag that tracks whether we have temporarily left Objective-C
scope to parse a C-like declaration, and uses that to better recover from
parse problems by stopping at possible method declarations and at @end. To
fix the original problem, we do /not/ stop at 'namespace' when in an
Objective-C @interface or @protocol context (but still do in @implementation).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159941 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/Parse/Parser.h')
-rw-r--r-- | include/clang/Parse/Parser.h | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index b9414a4051..14ae6604b2 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -23,6 +23,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SaveAndRestore.h" #include <stack> namespace clang { @@ -83,6 +84,7 @@ class Parser : public CodeCompletionHandler { friend class ColonProtectionRAIIObject; friend class InMessageExpressionRAIIObject; friend class PoisonSEHIdentifiersRAIIObject; + friend class ObjCDeclContextSwitch; friend class ParenBraceBracketBalancer; friend class BalancedDelimiterTracker; @@ -203,6 +205,13 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *getSEHExceptKeyword(); + /// True if we are within an Objective-C container while parsing C-like decls. + /// + /// This is necessary because Sema thinks we have left the container + /// to parse the C-like decls, meaning Actions.getObjCDeclContext() will + /// be NULL. + bool ParsingInObjCContainer; + bool SkipFunctionBodies; public: @@ -556,9 +565,11 @@ private: class ObjCDeclContextSwitch { Parser &P; Decl *DC; + SaveAndRestore<bool> WithinObjCContainer; public: - explicit ObjCDeclContextSwitch(Parser &p) : P(p), - DC(p.getObjCDeclContext()) { + explicit ObjCDeclContextSwitch(Parser &p) + : P(p), DC(p.getObjCDeclContext()), + WithinObjCContainer(P.ParsingInObjCContainer, DC != 0) { if (DC) P.Actions.ActOnObjCTemporaryExitContainerContext(cast<DeclContext>(DC)); } |