summaryrefslogtreecommitdiff
path: root/clang-r353983/include/clang/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'clang-r353983/include/clang/Parse')
-rw-r--r--clang-r353983/include/clang/Parse/AttrParserStringSwitches.inc121
-rw-r--r--clang-r353983/include/clang/Parse/AttrSubMatchRulesParserStringSwitches.inc88
-rw-r--r--clang-r353983/include/clang/Parse/LoopHint.h44
-rw-r--r--clang-r353983/include/clang/Parse/ParseAST.h51
-rw-r--r--clang-r353983/include/clang/Parse/ParseDiagnostic.h14
-rw-r--r--clang-r353983/include/clang/Parse/Parser.h3022
-rw-r--r--clang-r353983/include/clang/Parse/RAIIObjectsForParser.h465
7 files changed, 3805 insertions, 0 deletions
diff --git a/clang-r353983/include/clang/Parse/AttrParserStringSwitches.inc b/clang-r353983/include/clang/Parse/AttrParserStringSwitches.inc
new file mode 100644
index 00000000..2e90aedb
--- /dev/null
+++ b/clang-r353983/include/clang/Parse/AttrParserStringSwitches.inc
@@ -0,0 +1,121 @@
+/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
+|* *|
+|* Parser-related llvm::StringSwitch cases *|
+|* *|
+|* Automatically generated file, do not edit! *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)
+.Case("acquire_capability", true)
+.Case("acquire_shared_capability", true)
+.Case("exclusive_lock_function", true)
+.Case("shared_lock_function", true)
+.Case("acquired_after", true)
+.Case("acquired_before", true)
+.Case("assert_capability", true)
+.Case("assert_shared_capability", true)
+.Case("assert_exclusive_lock", true)
+.Case("assert_shared_lock", true)
+.Case("exclusive_trylock_function", true)
+.Case("guarded_by", true)
+.Case("lock_returned", true)
+.Case("locks_excluded", true)
+.Case("pt_guarded_by", true)
+.Case("release_capability", true)
+.Case("release_shared_capability", true)
+.Case("release_generic_capability", true)
+.Case("unlock_function", true)
+.Case("requires_capability", true)
+.Case("exclusive_locks_required", true)
+.Case("requires_shared_capability", true)
+.Case("shared_locks_required", true)
+.Case("shared_trylock_function", true)
+.Case("try_acquire_capability", true)
+.Case("try_acquire_shared_capability", true)
+#endif // CLANG_ATTR_ARG_CONTEXT_LIST
+
+#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)
+.Case("interrupt", true)
+.Case("argument_with_type_tag", true)
+.Case("pointer_with_type_tag", true)
+.Case("availability", true)
+.Case("blocks", true)
+.Case("callable_when", true)
+.Case("consumable", true)
+.Case("enum_extensibility", true)
+.Case("format", true)
+.Case("loop", true)
+.Case("unroll", true)
+.Case("nounroll", true)
+.Case("unroll_and_jam", true)
+.Case("nounroll_and_jam", true)
+.Case("interrupt", true)
+.Case("mode", true)
+.Case("declare simd", true)
+.Case("declare target", true)
+.Case("objc_bridge", true)
+.Case("objc_bridge_mutable", true)
+.Case("objc_bridge_related", true)
+.Case("objc_gc", true)
+.Case("objc_method_family", true)
+.Case("objc_ownership", true)
+.Case("ownership_holds", true)
+.Case("ownership_returns", true)
+.Case("ownership_takes", true)
+.Case("param_typestate", true)
+.Case("pcs", true)
+.Case("interrupt", true)
+.Case("return_typestate", true)
+.Case("set_typestate", true)
+.Case("test_typestate", true)
+.Case("type_tag_for_datatype", true)
+.Case("type_visibility", true)
+.Case("visibility", true)
+#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST
+
+#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)
+.Case("cpu_dispatch", true)
+.Case("cpu_specific", true)
+.Case("callback", true)
+#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
+
+#if defined(CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST)
+.Case("callback", true)
+#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
+
+#if defined(CLANG_ATTR_TYPE_ARG_LIST)
+.Case("iboutletcollection", true)
+.Case("vec_type_hint", true)
+#endif // CLANG_ATTR_TYPE_ARG_LIST
+
+#if defined(CLANG_ATTR_LATE_PARSED_LIST)
+.Case("acquire_capability", 1)
+.Case("acquire_shared_capability", 1)
+.Case("exclusive_lock_function", 1)
+.Case("shared_lock_function", 1)
+.Case("acquired_after", 1)
+.Case("acquired_before", 1)
+.Case("assert_capability", 1)
+.Case("assert_shared_capability", 1)
+.Case("assert_exclusive_lock", 1)
+.Case("assert_shared_lock", 1)
+.Case("diagnose_if", 1)
+.Case("exclusive_trylock_function", 1)
+.Case("guarded_by", 1)
+.Case("lock_returned", 1)
+.Case("locks_excluded", 1)
+.Case("pt_guarded_by", 1)
+.Case("release_capability", 1)
+.Case("release_shared_capability", 1)
+.Case("release_generic_capability", 1)
+.Case("unlock_function", 1)
+.Case("requires_capability", 1)
+.Case("exclusive_locks_required", 1)
+.Case("requires_shared_capability", 1)
+.Case("shared_locks_required", 1)
+.Case("shared_trylock_function", 1)
+.Case("try_acquire_capability", 1)
+.Case("try_acquire_shared_capability", 1)
+#endif // CLANG_ATTR_LATE_PARSED_LIST
+
diff --git a/clang-r353983/include/clang/Parse/AttrSubMatchRulesParserStringSwitches.inc b/clang-r353983/include/clang/Parse/AttrSubMatchRulesParserStringSwitches.inc
new file mode 100644
index 00000000..22dcf9f3
--- /dev/null
+++ b/clang-r353983/include/clang/Parse/AttrSubMatchRulesParserStringSwitches.inc
@@ -0,0 +1,88 @@
+Optional<attr::SubjectMatchRule> defaultIsAttributeSubjectMatchSubRuleFor(StringRef, bool) {
+ return None;
+}
+
+Optional<attr::SubjectMatchRule> isAttributeSubjectMatchSubRuleFor_function(StringRef Name, bool IsUnless) {
+ if (IsUnless)
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Default(None);
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Case("is_member", attr::SubjectMatchRule_function_is_member).
+ Default(None);
+}
+
+Optional<attr::SubjectMatchRule> isAttributeSubjectMatchSubRuleFor_hasType(StringRef Name, bool IsUnless) {
+ if (IsUnless)
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Default(None);
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Case("functionType", attr::SubjectMatchRule_hasType_functionType).
+ Default(None);
+}
+
+Optional<attr::SubjectMatchRule> isAttributeSubjectMatchSubRuleFor_record(StringRef Name, bool IsUnless) {
+ if (IsUnless)
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Case("is_union", attr::SubjectMatchRule_record_not_is_union).
+ Default(None);
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Default(None);
+}
+
+Optional<attr::SubjectMatchRule> isAttributeSubjectMatchSubRuleFor_variable(StringRef Name, bool IsUnless) {
+ if (IsUnless)
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Case("is_parameter", attr::SubjectMatchRule_variable_not_is_parameter).
+ Default(None);
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Case("is_thread_local", attr::SubjectMatchRule_variable_is_thread_local).
+ Case("is_global", attr::SubjectMatchRule_variable_is_global).
+ Case("is_parameter", attr::SubjectMatchRule_variable_is_parameter).
+ Default(None);
+}
+
+Optional<attr::SubjectMatchRule> isAttributeSubjectMatchSubRuleFor_objc_method(StringRef Name, bool IsUnless) {
+ if (IsUnless)
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Default(None);
+ return llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).
+ Case("is_instance", attr::SubjectMatchRule_objc_method_is_instance).
+ Default(None);
+}
+
+std::pair<Optional<attr::SubjectMatchRule>, Optional<attr::SubjectMatchRule> (*)(StringRef, bool)> isAttributeSubjectMatchRule(StringRef Name) {
+ return llvm::StringSwitch<std::pair<Optional<attr::SubjectMatchRule>, Optional<attr::SubjectMatchRule> (*) (StringRef, bool)>>(Name).
+ Case("block", std::make_pair(attr::SubjectMatchRule_block, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("enum", std::make_pair(attr::SubjectMatchRule_enum, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("enum_constant", std::make_pair(attr::SubjectMatchRule_enum_constant, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("field", std::make_pair(attr::SubjectMatchRule_field, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("function", std::make_pair(attr::SubjectMatchRule_function, isAttributeSubjectMatchSubRuleFor_function)).
+ Case("namespace", std::make_pair(attr::SubjectMatchRule_namespace, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("objc_category", std::make_pair(attr::SubjectMatchRule_objc_category, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("objc_interface", std::make_pair(attr::SubjectMatchRule_objc_interface, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("objc_method", std::make_pair(attr::SubjectMatchRule_objc_method, isAttributeSubjectMatchSubRuleFor_objc_method)).
+ Case("objc_property", std::make_pair(attr::SubjectMatchRule_objc_property, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("objc_protocol", std::make_pair(attr::SubjectMatchRule_objc_protocol, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("record", std::make_pair(attr::SubjectMatchRule_record, isAttributeSubjectMatchSubRuleFor_record)).
+ Case("hasType", std::make_pair(attr::SubjectMatchRule_hasType_abstract, isAttributeSubjectMatchSubRuleFor_hasType)).
+ Case("type_alias", std::make_pair(attr::SubjectMatchRule_type_alias, defaultIsAttributeSubjectMatchSubRuleFor)).
+ Case("variable", std::make_pair(attr::SubjectMatchRule_variable, isAttributeSubjectMatchSubRuleFor_variable)).
+ Default(std::make_pair(None, defaultIsAttributeSubjectMatchSubRuleFor));
+}
+
+const char *validAttributeSubjectMatchSubRules(attr::SubjectMatchRule Rule) {
+ switch (Rule) {
+ case attr::SubjectMatchRule_function:
+ return "'is_member'";
+ case attr::SubjectMatchRule_hasType_abstract:
+ return "'functionType'";
+ case attr::SubjectMatchRule_record:
+ return "'unless(is_union)'";
+ case attr::SubjectMatchRule_variable:
+ return "'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'";
+ case attr::SubjectMatchRule_objc_method:
+ return "'is_instance'";
+ default: return nullptr;
+ }
+}
+
diff --git a/clang-r353983/include/clang/Parse/LoopHint.h b/clang-r353983/include/clang/Parse/LoopHint.h
new file mode 100644
index 00000000..6e363f72
--- /dev/null
+++ b/clang-r353983/include/clang/Parse/LoopHint.h
@@ -0,0 +1,44 @@
+//===--- LoopHint.h - Types for LoopHint ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_LOOPHINT_H
+#define LLVM_CLANG_PARSE_LOOPHINT_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/ParsedAttr.h"
+
+namespace clang {
+
+/// Loop optimization hint for loop and unroll pragmas.
+struct LoopHint {
+ // Source range of the directive.
+ SourceRange Range;
+ // Identifier corresponding to the name of the pragma. "loop" for
+ // "#pragma clang loop" directives and "unroll" for "#pragma unroll"
+ // hints.
+ IdentifierLoc *PragmaNameLoc;
+ // Name of the loop hint. Examples: "unroll", "vectorize". In the
+ // "#pragma unroll" and "#pragma nounroll" cases, this is identical to
+ // PragmaNameLoc.
+ IdentifierLoc *OptionLoc;
+ // Identifier for the hint state argument. If null, then the state is
+ // default value such as for "#pragma unroll".
+ IdentifierLoc *StateLoc;
+ // Expression for the hint argument if it exists, null otherwise.
+ Expr *ValueExpr;
+
+ LoopHint()
+ : PragmaNameLoc(nullptr), OptionLoc(nullptr), StateLoc(nullptr),
+ ValueExpr(nullptr) {}
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_PARSE_LOOPHINT_H
diff --git a/clang-r353983/include/clang/Parse/ParseAST.h b/clang-r353983/include/clang/Parse/ParseAST.h
new file mode 100644
index 00000000..3a21f04f
--- /dev/null
+++ b/clang-r353983/include/clang/Parse/ParseAST.h
@@ -0,0 +1,51 @@
+//===--- ParseAST.h - Define the ParseAST method ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the clang::ParseAST method.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_PARSEAST_H
+#define LLVM_CLANG_PARSE_PARSEAST_H
+
+#include "clang/Basic/LangOptions.h"
+
+namespace clang {
+ class Preprocessor;
+ class ASTConsumer;
+ class ASTContext;
+ class CodeCompleteConsumer;
+ class Sema;
+
+ /// Parse the entire file specified, notifying the ASTConsumer as
+ /// the file is parsed.
+ ///
+ /// This operation inserts the parsed decls into the translation
+ /// unit held by Ctx.
+ ///
+ /// \param PrintStats Whether to print LLVM statistics related to parsing.
+ /// \param TUKind The kind of translation unit being parsed.
+ /// \param CompletionConsumer If given, an object to consume code completion
+ /// results.
+ /// \param SkipFunctionBodies Whether to skip parsing of function bodies.
+ /// This option can be used, for example, to speed up searches for
+ /// declarations/definitions when indexing.
+ void ParseAST(Preprocessor &pp, ASTConsumer *C,
+ ASTContext &Ctx, bool PrintStats = false,
+ TranslationUnitKind TUKind = TU_Complete,
+ CodeCompleteConsumer *CompletionConsumer = nullptr,
+ bool SkipFunctionBodies = false);
+
+ /// Parse the main file known to the preprocessor, producing an
+ /// abstract syntax tree.
+ void ParseAST(Sema &S, bool PrintStats = false,
+ bool SkipFunctionBodies = false);
+
+} // end namespace clang
+
+#endif
diff --git a/clang-r353983/include/clang/Parse/ParseDiagnostic.h b/clang-r353983/include/clang/Parse/ParseDiagnostic.h
new file mode 100644
index 00000000..f174464b
--- /dev/null
+++ b/clang-r353983/include/clang/Parse/ParseDiagnostic.h
@@ -0,0 +1,14 @@
+//===--- DiagnosticParse.h - Diagnostics for libparse -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H
+#define LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H
+
+#include "clang/Basic/DiagnosticParse.h"
+
+#endif
diff --git a/clang-r353983/include/clang/Parse/Parser.h b/clang-r353983/include/clang/Parse/Parser.h
new file mode 100644
index 00000000..f5c70e71
--- /dev/null
+++ b/clang-r353983/include/clang/Parse/Parser.h
@@ -0,0 +1,3022 @@
+//===--- Parser.h - C Language Parser ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Parser interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_PARSER_H
+#define LLVM_CLANG_PARSE_PARSER_H
+
+#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/Availability.h"
+#include "clang/Basic/BitmaskEnum.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/OperatorPrecedence.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include <memory>
+#include <stack>
+
+namespace clang {
+ class PragmaHandler;
+ class Scope;
+ class BalancedDelimiterTracker;
+ class CorrectionCandidateCallback;
+ class DeclGroupRef;
+ class DiagnosticBuilder;
+ struct LoopHint;
+ class Parser;
+ class ParsingDeclRAIIObject;
+ class ParsingDeclSpec;
+ class ParsingDeclarator;
+ class ParsingFieldDeclarator;
+ class ColonProtectionRAIIObject;
+ class InMessageExpressionRAIIObject;
+ class PoisonSEHIdentifiersRAIIObject;
+ class OMPClause;
+ class ObjCTypeParamList;
+ class ObjCTypeParameter;
+
+/// Parser - This implements a parser for the C family of languages. After
+/// parsing units of the grammar, productions are invoked to handle whatever has
+/// been read.
+///
+class Parser : public CodeCompletionHandler {
+ friend class ColonProtectionRAIIObject;
+ friend class InMessageExpressionRAIIObject;
+ friend class PoisonSEHIdentifiersRAIIObject;
+ friend class ObjCDeclContextSwitch;
+ friend class ParenBraceBracketBalancer;
+ friend class BalancedDelimiterTracker;
+
+ Preprocessor &PP;
+
+ /// Tok - The current token we are peeking ahead. All parsing methods assume
+ /// that this is valid.
+ Token Tok;
+
+ // PrevTokLocation - The location of the token we previously
+ // consumed. This token is used for diagnostics where we expected to
+ // see a token following another token (e.g., the ';' at the end of
+ // a statement).
+ SourceLocation PrevTokLocation;
+
+ /// Tracks an expected type for the current token when parsing an expression.
+ /// Used by code completion for ranking.
+ PreferredTypeBuilder PreferredType;
+
+ unsigned short ParenCount = 0, BracketCount = 0, BraceCount = 0;
+ unsigned short MisplacedModuleBeginCount = 0;
+
+ /// Actions - These are the callbacks we invoke as we parse various constructs
+ /// in the file.
+ Sema &Actions;
+
+ DiagnosticsEngine &Diags;
+
+ /// ScopeCache - Cache scopes to reduce malloc traffic.
+ enum { ScopeCacheSize = 16 };
+ unsigned NumCachedScopes;
+ Scope *ScopeCache[ScopeCacheSize];
+
+ /// Identifiers used for SEH handling in Borland. These are only
+ /// allowed in particular circumstances
+ // __except block
+ IdentifierInfo *Ident__exception_code,
+ *Ident___exception_code,
+ *Ident_GetExceptionCode;
+ // __except filter expression
+ IdentifierInfo *Ident__exception_info,
+ *Ident___exception_info,
+ *Ident_GetExceptionInfo;
+ // __finally
+ IdentifierInfo *Ident__abnormal_termination,
+ *Ident___abnormal_termination,
+ *Ident_AbnormalTermination;
+
+ /// Contextual keywords for Microsoft extensions.
+ IdentifierInfo *Ident__except;
+ mutable IdentifierInfo *Ident_sealed;
+
+ /// Ident_super - IdentifierInfo for "super", to support fast
+ /// comparison.
+ IdentifierInfo *Ident_super;
+ /// Ident_vector, Ident_bool - cached IdentifierInfos for "vector" and
+ /// "bool" fast comparison. Only present if AltiVec or ZVector are enabled.
+ IdentifierInfo *Ident_vector;
+ IdentifierInfo *Ident_bool;
+ /// Ident_pixel - cached IdentifierInfos for "pixel" fast comparison.
+ /// Only present if AltiVec enabled.
+ IdentifierInfo *Ident_pixel;
+
+ /// Objective-C contextual keywords.
+ IdentifierInfo *Ident_instancetype;
+
+ /// Identifier for "introduced".
+ IdentifierInfo *Ident_introduced;
+
+ /// Identifier for "deprecated".
+ IdentifierInfo *Ident_deprecated;
+
+ /// Identifier for "obsoleted".
+ IdentifierInfo *Ident_obsoleted;
+
+ /// Identifier for "unavailable".
+ IdentifierInfo *Ident_unavailable;
+
+ /// Identifier for "message".
+ IdentifierInfo *Ident_message;
+
+ /// Identifier for "strict".
+ IdentifierInfo *Ident_strict;
+
+ /// Identifier for "replacement".
+ IdentifierInfo *Ident_replacement;
+
+ /// Identifiers used by the 'external_source_symbol' attribute.
+ IdentifierInfo *Ident_language, *Ident_defined_in,
+ *Ident_generated_declaration;
+
+ /// C++0x contextual keywords.
+ mutable IdentifierInfo *Ident_final;
+ mutable IdentifierInfo *Ident_GNU_final;
+ mutable IdentifierInfo *Ident_override;
+
+ // C++ type trait keywords that can be reverted to identifiers and still be
+ // used as type traits.
+ llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertibleTypeTraits;
+
+ std::unique_ptr<PragmaHandler> AlignHandler;
+ std::unique_ptr<PragmaHandler> GCCVisibilityHandler;
+ std::unique_ptr<PragmaHandler> OptionsHandler;
+ std::unique_ptr<PragmaHandler> PackHandler;
+ std::unique_ptr<PragmaHandler> MSStructHandler;
+ std::unique_ptr<PragmaHandler> UnusedHandler;
+ std::unique_ptr<PragmaHandler> WeakHandler;
+ std::unique_ptr<PragmaHandler> RedefineExtnameHandler;
+ std::unique_ptr<PragmaHandler> FPContractHandler;
+ std::unique_ptr<PragmaHandler> OpenCLExtensionHandler;
+ std::unique_ptr<PragmaHandler> OpenMPHandler;
+ std::unique_ptr<PragmaHandler> PCSectionHandler;
+ std::unique_ptr<PragmaHandler> MSCommentHandler;
+ std::unique_ptr<PragmaHandler> MSDetectMismatchHandler;
+ std::unique_ptr<PragmaHandler> MSPointersToMembers;
+ std::unique_ptr<PragmaHandler> MSVtorDisp;
+ std::unique_ptr<PragmaHandler> MSInitSeg;
+ std::unique_ptr<PragmaHandler> MSDataSeg;
+ std::unique_ptr<PragmaHandler> MSBSSSeg;
+ std::unique_ptr<PragmaHandler> MSConstSeg;
+ std::unique_ptr<PragmaHandler> MSCodeSeg;
+ std::unique_ptr<PragmaHandler> MSSection;
+ std::unique_ptr<PragmaHandler> MSRuntimeChecks;
+ std::unique_ptr<PragmaHandler> MSIntrinsic;
+ std::unique_ptr<PragmaHandler> MSOptimize;
+ std::unique_ptr<PragmaHandler> CUDAForceHostDeviceHandler;
+ std::unique_ptr<PragmaHandler> OptimizeHandler;
+ std::unique_ptr<PragmaHandler> LoopHintHandler;
+ std::unique_ptr<PragmaHandler> UnrollHintHandler;
+ std::unique_ptr<PragmaHandler> NoUnrollHintHandler;
+ std::unique_ptr<PragmaHandler> UnrollAndJamHintHandler;
+ std::unique_ptr<PragmaHandler> NoUnrollAndJamHintHandler;
+ std::unique_ptr<PragmaHandler> FPHandler;
+ std::unique_ptr<PragmaHandler> STDCFENVHandler;
+ std::unique_ptr<PragmaHandler> STDCCXLIMITHandler;
+ std::unique_ptr<PragmaHandler> STDCUnknownHandler;
+ std::unique_ptr<PragmaHandler> AttributePragmaHandler;
+
+ std::unique_ptr<CommentHandler> CommentSemaHandler;
+
+ /// Whether the '>' token acts as an operator or not. This will be
+ /// true except when we are parsing an expression within a C++
+ /// template argument list, where the '>' closes the template
+ /// argument list.
+ bool GreaterThanIsOperator;
+
+ /// ColonIsSacred - When this is false, we aggressively try to recover from
+ /// code like "foo : bar" as if it were a typo for "foo :: bar". This is not
+ /// safe in case statements and a few other things. This is managed by the
+ /// ColonProtectionRAIIObject RAII object.
+ bool ColonIsSacred;
+
+ /// When true, we are directly inside an Objective-C message
+ /// send expression.
+ ///
+ /// This is managed by the \c InMessageExpressionRAIIObject class, and
+ /// should not be set directly.
+ bool InMessageExpression;
+
+ /// Gets set to true after calling ProduceSignatureHelp, it is for a
+ /// workaround to make sure ProduceSignatureHelp is only called at the deepest
+ /// function call.
+ bool CalledSignatureHelp = false;
+
+ /// The "depth" of the template parameters currently being parsed.
+ unsigned TemplateParameterDepth;
+
+ /// RAII class that manages the template parameter depth.
+ class TemplateParameterDepthRAII {
+ unsigned &Depth;
+ unsigned AddedLevels;
+ public:
+ explicit TemplateParameterDepthRAII(unsigned &Depth)
+ : Depth(Depth), AddedLevels(0) {}
+
+ ~TemplateParameterDepthRAII() {
+ Depth -= AddedLevels;
+ }
+
+ void operator++() {
+ ++Depth;
+ ++AddedLevels;
+ }
+ void addDepth(unsigned D) {
+ Depth += D;
+ AddedLevels += D;
+ }
+ unsigned getDepth() const { return Depth; }
+ };
+
+ /// Factory object for creating ParsedAttr objects.
+ AttributeFactory AttrFactory;
+
+ /// Gathers and cleans up TemplateIdAnnotations when parsing of a
+ /// top-level declaration is finished.
+ SmallVector<TemplateIdAnnotation *, 16> TemplateIds;
+
+ /// Identifiers which have been declared within a tentative parse.
+ SmallVector<IdentifierInfo *, 8> TentativelyDeclaredIdentifiers;
+
+ /// Tracker for '<' tokens that might have been intended to be treated as an
+ /// angle bracket instead of a less-than comparison.
+ ///
+ /// This happens when the user intends to form a template-id, but typoes the
+ /// template-name or forgets a 'template' keyword for a dependent template
+ /// name.
+ ///
+ /// We track these locations from the point where we see a '<' with a
+ /// name-like expression on its left until we see a '>' or '>>' that might
+ /// match it.
+ struct AngleBracketTracker {
+ /// Flags used to rank candidate template names when there is more than one
+ /// '<' in a scope.
+ enum Priority : unsigned short {
+ /// A non-dependent name that is a potential typo for a template name.
+ PotentialTypo = 0x0,
+ /// A dependent name that might instantiate to a template-name.
+ DependentName = 0x2,
+
+ /// A space appears before the '<' token.
+ SpaceBeforeLess = 0x0,
+ /// No space before the '<' token
+ NoSpaceBeforeLess = 0x1,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ DependentName)
+ };
+
+ struct Loc {
+ Expr *TemplateName;
+ SourceLocation LessLoc;
+ AngleBracketTracker::Priority Priority;
+ unsigned short ParenCount, BracketCount, BraceCount;
+
+ bool isActive(Parser &P) const {
+ return P.ParenCount == ParenCount && P.BracketCount == BracketCount &&
+ P.BraceCount == BraceCount;
+ }
+
+ bool isActiveOrNested(Parser &P) const {
+ return isActive(P) || P.ParenCount > ParenCount ||
+ P.BracketCount > BracketCount || P.BraceCount > BraceCount;
+ }
+ };
+
+ SmallVector<Loc, 8> Locs;
+
+ /// Add an expression that might have been intended to be a template name.
+ /// In the case of ambiguity, we arbitrarily select the innermost such
+ /// expression, for example in 'foo < bar < baz', 'bar' is the current
+ /// candidate. No attempt is made to track that 'foo' is also a candidate
+ /// for the case where we see a second suspicious '>' token.
+ void add(Parser &P, Expr *TemplateName, SourceLocation LessLoc,
+ Priority Prio) {
+ if (!Locs.empty() && Locs.back().isActive(P)) {
+ if (Locs.back().Priority <= Prio) {
+ Locs.back().TemplateName = TemplateName;
+ Locs.back().LessLoc = LessLoc;
+ Locs.back().Priority = Prio;
+ }
+ } else {
+ Locs.push_back({TemplateName, LessLoc, Prio,
+ P.ParenCount, P.BracketCount, P.BraceCount});
+ }
+ }
+
+ /// Mark the current potential missing template location as having been
+ /// handled (this happens if we pass a "corresponding" '>' or '>>' token
+ /// or leave a bracket scope).
+ void clear(Parser &P) {
+ while (!Locs.empty() && Locs.back().isActiveOrNested(P))
+ Locs.pop_back();
+ }
+
+ /// Get the current enclosing expression that might hve been intended to be
+ /// a template name.
+ Loc *getCurrent(Parser &P) {
+ if (!Locs.empty() && Locs.back().isActive(P))
+ return &Locs.back();
+ return nullptr;
+ }
+ };
+
+ AngleBracketTracker AngleBrackets;
+
+ 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;
+
+ /// Whether to skip parsing of function bodies.
+ ///
+ /// This option can be used, for example, to speed up searches for
+ /// declarations/definitions when indexing.
+ bool SkipFunctionBodies;
+
+ /// The location of the expression statement that is being parsed right now.
+ /// Used to determine if an expression that is being parsed is a statement or
+ /// just a regular sub-expression.
+ SourceLocation ExprStatementTokLoc;
+
+ /// Tests whether an expression value is discarded based on token lookahead.
+ /// It will return true if the lexer is currently processing the })
+ /// terminating a GNU statement expression and false otherwise.
+ bool isExprValueDiscarded();
+
+public:
+ Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
+ ~Parser() override;
+
+ const LangOptions &getLangOpts() const { return PP.getLangOpts(); }
+ 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(); }
+ void incrementMSManglingNumber() const {
+ return Actions.incrementMSManglingNumber();
+ }
+
+ Decl *getObjCDeclContext() const { return Actions.getObjCDeclContext(); }
+
+ // Type forwarding. All of these are statically 'void*', but they may all be
+ // different actual classes based on the actions in place.
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+
+ typedef SmallVector<TemplateParameterList *, 4> TemplateParameterLists;
+
+ typedef Sema::FullExprArg FullExprArg;
+
+ // Parsing methods.
+
+ /// Initialize - Warm up the parser.
+ ///
+ void Initialize();
+
+ /// Parse the first top-level declaration in a translation unit.
+ bool ParseFirstTopLevelDecl(DeclGroupPtrTy &Result);
+
+ /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
+ /// the EOF was encountered.
+ bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
+ bool ParseTopLevelDecl() {
+ DeclGroupPtrTy Result;
+ return ParseTopLevelDecl(Result);
+ }
+
+ /// ConsumeToken - Consume the current 'peek token' and lex the next one.
+ /// This does not work with special tokens: string literals, code completion,
+ /// annotation tokens and balanced tokens must be handled using the specific
+ /// consume methods.
+ /// Returns the location of the consumed token.
+ SourceLocation ConsumeToken() {
+ assert(!isTokenSpecial() &&
+ "Should consume special tokens with Consume*Token");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ bool TryConsumeToken(tok::TokenKind Expected) {
+ if (Tok.isNot(Expected))
+ return false;
+ assert(!isTokenSpecial() &&
+ "Should consume special tokens with Consume*Token");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return true;
+ }
+
+ bool TryConsumeToken(tok::TokenKind Expected, SourceLocation &Loc) {
+ if (!TryConsumeToken(Expected))
+ return false;
+ Loc = PrevTokLocation;
+ return true;
+ }
+
+ /// ConsumeAnyToken - Dispatch to the right Consume* method based on the
+ /// current token type. This should only be used in cases where the type of
+ /// the token really isn't known, e.g. in error recovery.
+ SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) {
+ if (isTokenParen())
+ return ConsumeParen();
+ if (isTokenBracket())
+ return ConsumeBracket();
+ if (isTokenBrace())
+ return ConsumeBrace();
+ if (isTokenStringLiteral())
+ return ConsumeStringToken();
+ if (Tok.is(tok::code_completion))
+ return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken()
+ : handleUnexpectedCodeCompletionToken();
+ if (Tok.isAnnotation())
+ return ConsumeAnnotationToken();
+ return ConsumeToken();
+ }
+
+
+ SourceLocation getEndOfPreviousToken() {
+ return PP.getLocForEndOfToken(PrevTokLocation);
+ }
+
+ /// Retrieve the underscored keyword (_Nonnull, _Nullable) that corresponds
+ /// to the given nullability kind.
+ IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability) {
+ return Actions.getNullabilityKeyword(nullability);
+ }
+
+private:
+ //===--------------------------------------------------------------------===//
+ // Low-Level token peeking and consumption methods.
+ //
+
+ /// isTokenParen - Return true if the cur token is '(' or ')'.
+ bool isTokenParen() const {
+ return Tok.isOneOf(tok::l_paren, tok::r_paren);
+ }
+ /// isTokenBracket - Return true if the cur token is '[' or ']'.
+ bool isTokenBracket() const {
+ return Tok.isOneOf(tok::l_square, tok::r_square);
+ }
+ /// isTokenBrace - Return true if the cur token is '{' or '}'.
+ bool isTokenBrace() const {
+ return Tok.isOneOf(tok::l_brace, tok::r_brace);
+ }
+ /// isTokenStringLiteral - True if this token is a string-literal.
+ bool isTokenStringLiteral() const {
+ return tok::isStringLiteral(Tok.getKind());
+ }
+ /// isTokenSpecial - True if this token requires special consumption methods.
+ bool isTokenSpecial() const {
+ return isTokenStringLiteral() || isTokenParen() || isTokenBracket() ||
+ isTokenBrace() || Tok.is(tok::code_completion) || Tok.isAnnotation();
+ }
+
+ /// Returns true if the current token is '=' or is a type of '='.
+ /// For typos, give a fixit to '='
+ bool isTokenEqualOrEqualTypo();
+
+ /// Return the current token to the token stream and make the given
+ /// token the current token.
+ void UnconsumeToken(Token &Consumed) {
+ Token Next = Tok;
+ PP.EnterToken(Consumed);
+ PP.Lex(Tok);
+ PP.EnterToken(Next);
+ }
+
+ SourceLocation ConsumeAnnotationToken() {
+ assert(Tok.isAnnotation() && "wrong consume method");
+ SourceLocation Loc = Tok.getLocation();
+ PrevTokLocation = Tok.getAnnotationEndLoc();
+ PP.Lex(Tok);
+ return Loc;
+ }
+
+ /// ConsumeParen - This consume method keeps the paren count up-to-date.
+ ///
+ SourceLocation ConsumeParen() {
+ assert(isTokenParen() && "wrong consume method");
+ if (Tok.getKind() == tok::l_paren)
+ ++ParenCount;
+ else if (ParenCount) {
+ AngleBrackets.clear(*this);
+ --ParenCount; // Don't let unbalanced )'s drive the count negative.
+ }
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeBracket - This consume method keeps the bracket count up-to-date.
+ ///
+ SourceLocation ConsumeBracket() {
+ assert(isTokenBracket() && "wrong consume method");
+ if (Tok.getKind() == tok::l_square)
+ ++BracketCount;
+ else if (BracketCount) {
+ AngleBrackets.clear(*this);
+ --BracketCount; // Don't let unbalanced ]'s drive the count negative.
+ }
+
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeBrace - This consume method keeps the brace count up-to-date.
+ ///
+ SourceLocation ConsumeBrace() {
+ assert(isTokenBrace() && "wrong consume method");
+ if (Tok.getKind() == tok::l_brace)
+ ++BraceCount;
+ else if (BraceCount) {
+ AngleBrackets.clear(*this);
+ --BraceCount; // Don't let unbalanced }'s drive the count negative.
+ }
+
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeStringToken - Consume the current 'peek token', lexing a new one
+ /// and returning the token kind. This method is specific to strings, as it
+ /// handles string literal concatenation, as per C99 5.1.1.2, translation
+ /// phase #6.
+ SourceLocation ConsumeStringToken() {
+ assert(isTokenStringLiteral() &&
+ "Should only consume string literals with this method");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// Consume the current code-completion token.
+ ///
+ /// This routine can be called to consume the code-completion token and
+ /// continue processing in special cases where \c cutOffParsing() isn't
+ /// desired, such as token caching or completion with lookahead.
+ SourceLocation ConsumeCodeCompletionToken() {
+ assert(Tok.is(tok::code_completion));
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ ///\ brief When we are consuming a code-completion token without having
+ /// matched specific position in the grammar, provide code-completion results
+ /// based on context.
+ ///
+ /// \returns the source location of the code-completion token.
+ SourceLocation handleUnexpectedCodeCompletionToken();
+
+ /// Abruptly cut off parsing; mainly used when we have reached the
+ /// code-completion point.
+ void cutOffParsing() {
+ if (PP.isCodeCompletionEnabled())
+ PP.setCodeCompletionReached();
+ // Cut off parsing by acting as if we reached the end-of-file.
+ Tok.setKind(tok::eof);
+ }
+
+ /// Determine if we're at the end of the file or at a transition
+ /// between modules.
+ bool isEofOrEom() {
+ tok::TokenKind Kind = Tok.getKind();
+ return Kind == tok::eof || Kind == tok::annot_module_begin ||
+ Kind == tok::annot_module_end || Kind == tok::annot_module_include;
+ }
+
+ /// Checks if the \p Level is valid for use in a fold expression.
+ bool isFoldOperator(prec::Level Level) const;
+
+ /// Checks if the \p Kind is a valid operator for fold expressions.
+ bool isFoldOperator(tok::TokenKind Kind) const;
+
+ /// Initialize all pragma handlers.
+ void initializePragmaHandlers();
+
+ /// Destroy and reset all pragma handlers.
+ void resetPragmaHandlers();
+
+ /// Handle the annotation token produced for #pragma unused(...)
+ void HandlePragmaUnused();
+
+ /// Handle the annotation token produced for
+ /// #pragma GCC visibility...
+ void HandlePragmaVisibility();
+
+ /// Handle the annotation token produced for
+ /// #pragma pack...
+ void HandlePragmaPack();
+
+ /// Handle the annotation token produced for
+ /// #pragma ms_struct...
+ void HandlePragmaMSStruct();
+
+ /// Handle the annotation token produced for
+ /// #pragma comment...
+ void HandlePragmaMSComment();
+
+ void HandlePragmaMSPointersToMembers();
+
+ void HandlePragmaMSVtorDisp();
+
+ void HandlePragmaMSPragma();
+ bool HandlePragmaMSSection(StringRef PragmaName,
+ SourceLocation PragmaLocation);
+ bool HandlePragmaMSSegment(StringRef PragmaName,
+ SourceLocation PragmaLocation);
+ bool HandlePragmaMSInitSeg(StringRef PragmaName,
+ SourceLocation PragmaLocation);
+
+ /// Handle the annotation token produced for
+ /// #pragma align...
+ void HandlePragmaAlign();
+
+ /// Handle the annotation token produced for
+ /// #pragma clang __debug dump...
+ void HandlePragmaDump();
+
+ /// Handle the annotation token produced for
+ /// #pragma weak id...
+ void HandlePragmaWeak();
+
+ /// Handle the annotation token produced for
+ /// #pragma weak id = id...
+ void HandlePragmaWeakAlias();
+
+ /// Handle the annotation token produced for
+ /// #pragma redefine_extname...
+ void HandlePragmaRedefineExtname();
+
+ /// Handle the annotation token produced for
+ /// #pragma STDC FP_CONTRACT...
+ void HandlePragmaFPContract();
+
+ /// Handle the annotation token produced for
+ /// #pragma STDC FENV_ACCESS...
+ void HandlePragmaFEnvAccess();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma clang fp ...
+ void HandlePragmaFP();
+
+ /// Handle the annotation token produced for
+ /// #pragma OPENCL EXTENSION...
+ void HandlePragmaOpenCLExtension();
+
+ /// Handle the annotation token produced for
+ /// #pragma clang __debug captured
+ StmtResult HandlePragmaCaptured();
+
+ /// Handle the annotation token produced for
+ /// #pragma clang loop and #pragma unroll.
+ bool HandlePragmaLoopHint(LoopHint &Hint);
+
+ bool ParsePragmaAttributeSubjectMatchRuleSet(
+ attr::ParsedSubjectMatchRuleSet &SubjectMatchRules,
+ SourceLocation &AnyLoc, SourceLocation &LastMatchRuleEndLoc);
+
+ void HandlePragmaAttribute();
+
+ /// GetLookAheadToken - This peeks ahead N tokens and returns that token
+ /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
+ /// returns the token after Tok, etc.
+ ///
+ /// Note that this differs from the Preprocessor's LookAhead method, because
+ /// the Parser always has one token lexed that the preprocessor doesn't.
+ ///
+ const Token &GetLookAheadToken(unsigned N) {
+ if (N == 0 || Tok.is(tok::eof)) return Tok;
+ return PP.LookAhead(N-1);
+ }
+
+public:
+ /// NextToken - This peeks ahead one token and returns it without
+ /// consuming it.
+ const Token &NextToken() {
+ return PP.LookAhead(0);
+ }
+
+ /// getTypeAnnotation - Read a parsed type out of an annotation token.
+ static ParsedType getTypeAnnotation(const Token &Tok) {
+ return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
+ }
+
+private:
+ static void setTypeAnnotation(Token &Tok, ParsedType T) {
+ Tok.setAnnotationValue(T.getAsOpaquePtr());
+ }
+
+ /// Read an already-translated primary expression out of an annotation
+ /// token.
+ static ExprResult getExprAnnotation(const Token &Tok) {
+ return ExprResult::getFromOpaquePointer(Tok.getAnnotationValue());
+ }
+
+ /// Set the primary expression corresponding to the given annotation
+ /// token.
+ static void setExprAnnotation(Token &Tok, ExprResult ER) {
+ Tok.setAnnotationValue(ER.getAsOpaquePointer());
+ }
+
+public:
+ // If NeedType is true, then TryAnnotateTypeOrScopeToken will try harder to
+ // find a type name by attempting typo correction.
+ bool TryAnnotateTypeOrScopeToken();
+ bool TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS,
+ bool IsNewScope);
+ bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
+
+private:
+ enum AnnotatedNameKind {
+ /// Annotation has failed and emitted an error.
+ ANK_Error,
+ /// The identifier is a tentatively-declared name.
+ ANK_TentativeDecl,
+ /// The identifier is a template name. FIXME: Add an annotation for that.
+ ANK_TemplateName,
+ /// The identifier can't be resolved.
+ ANK_Unresolved,
+ /// Annotation was successful.
+ ANK_Success
+ };
+ AnnotatedNameKind
+ TryAnnotateName(bool IsAddressOfOperand,
+ std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr);
+
+ /// Push a tok::annot_cxxscope token onto the token stream.
+ void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation);
+
+ /// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens,
+ /// replacing them with the non-context-sensitive keywords. This returns
+ /// true if the token was replaced.
+ bool TryAltiVecToken(DeclSpec &DS, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ bool &isInvalid) {
+ if (!getLangOpts().AltiVec && !getLangOpts().ZVector)
+ return false;
+
+ if (Tok.getIdentifierInfo() != Ident_vector &&
+ Tok.getIdentifierInfo() != Ident_bool &&
+ (!getLangOpts().AltiVec || Tok.getIdentifierInfo() != Ident_pixel))
+ return false;
+
+ return TryAltiVecTokenOutOfLine(DS, Loc, PrevSpec, DiagID, isInvalid);
+ }
+
+ /// TryAltiVecVectorToken - Check for context-sensitive AltiVec vector
+ /// identifier token, replacing it with the non-context-sensitive __vector.
+ /// This returns true if the token was replaced.
+ bool TryAltiVecVectorToken() {
+ if ((!getLangOpts().AltiVec && !getLangOpts().ZVector) ||
+ Tok.getIdentifierInfo() != Ident_vector) return false;
+ return TryAltiVecVectorTokenOutOfLine();
+ }
+
+ bool TryAltiVecVectorTokenOutOfLine();
+ bool TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ bool &isInvalid);
+
+ /// Returns true if the current token is the identifier 'instancetype'.
+ ///
+ /// Should only be used in Objective-C language modes.
+ bool isObjCInstancetype() {
+ assert(getLangOpts().ObjC);
+ if (Tok.isAnnotation())
+ return false;
+ if (!Ident_instancetype)
+ Ident_instancetype = PP.getIdentifierInfo("instancetype");
+ return Tok.getIdentifierInfo() == Ident_instancetype;
+ }
+
+ /// TryKeywordIdentFallback - For compatibility with system headers using
+ /// keywords as identifiers, attempt to convert the current token to an
+ /// identifier and optionally disable the keyword for the remainder of the
+ /// translation unit. This returns false if the token was not replaced,
+ /// otherwise emits a diagnostic and returns true.
+ bool TryKeywordIdentFallback(bool DisableKeyword);
+
+ /// Get the TemplateIdAnnotation from the token.
+ TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);
+
+ /// TentativeParsingAction - An object that is used as a kind of "tentative
+ /// parsing transaction". It gets instantiated to mark the token position and
+ /// after the token consumption is done, Commit() or Revert() is called to
+ /// either "commit the consumed tokens" or revert to the previously marked
+ /// token position. Example:
+ ///
+ /// TentativeParsingAction TPA(*this);
+ /// ConsumeToken();
+ /// ....
+ /// TPA.Revert();
+ ///
+ class TentativeParsingAction {
+ Parser &P;
+ PreferredTypeBuilder PrevPreferredType;
+ Token PrevTok;
+ size_t PrevTentativelyDeclaredIdentifierCount;
+ unsigned short PrevParenCount, PrevBracketCount, PrevBraceCount;
+ bool isActive;
+
+ public:
+ explicit TentativeParsingAction(Parser& p) : P(p) {
+ PrevPreferredType = P.PreferredType;
+ PrevTok = P.Tok;
+ PrevTentativelyDeclaredIdentifierCount =
+ P.TentativelyDeclaredIdentifiers.size();
+ PrevParenCount = P.ParenCount;
+ PrevBracketCount = P.BracketCount;
+ PrevBraceCount = P.BraceCount;
+ P.PP.EnableBacktrackAtThisPos();
+ isActive = true;
+ }
+ void Commit() {
+ assert(isActive && "Parsing action was finished!");
+ P.TentativelyDeclaredIdentifiers.resize(
+ PrevTentativelyDeclaredIdentifierCount);
+ P.PP.CommitBacktrackedTokens();
+ isActive = false;
+ }
+ void Revert() {
+ assert(isActive && "Parsing action was finished!");
+ P.PP.Backtrack();
+ P.PreferredType = PrevPreferredType;
+ P.Tok = PrevTok;
+ P.TentativelyDeclaredIdentifiers.resize(
+ PrevTentativelyDeclaredIdentifierCount);
+ P.ParenCount = PrevParenCount;
+ P.BracketCount = PrevBracketCount;
+ P.BraceCount = PrevBraceCount;
+ isActive = false;
+ }
+ ~TentativeParsingAction() {
+ assert(!isActive && "Forgot to call Commit or Revert!");
+ }
+ };
+ /// A TentativeParsingAction that automatically reverts in its destructor.
+ /// Useful for disambiguation parses that will always be reverted.
+ class RevertingTentativeParsingAction
+ : private Parser::TentativeParsingAction {
+ public:
+ RevertingTentativeParsingAction(Parser &P)
+ : Parser::TentativeParsingAction(P) {}
+ ~RevertingTentativeParsingAction() { Revert(); }
+ };
+
+ class UnannotatedTentativeParsingAction;
+
+ /// ObjCDeclContextSwitch - An object used to switch context from
+ /// an objective-c decl context to its enclosing decl context and
+ /// back.
+ class ObjCDeclContextSwitch {
+ Parser &P;
+ Decl *DC;
+ SaveAndRestore<bool> WithinObjCContainer;
+ public:
+ explicit ObjCDeclContextSwitch(Parser &p)
+ : P(p), DC(p.getObjCDeclContext()),
+ WithinObjCContainer(P.ParsingInObjCContainer, DC != nullptr) {
+ if (DC)
+ P.Actions.ActOnObjCTemporaryExitContainerContext(cast<DeclContext>(DC));
+ }
+ ~ObjCDeclContextSwitch() {
+ if (DC)
+ P.Actions.ActOnObjCReenterContainerContext(cast<DeclContext>(DC));
+ }
+ };
+
+ /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
+ /// input. If so, it is consumed and false is returned.
+ ///
+ /// If a trivial punctuator misspelling is encountered, a FixIt error
+ /// diagnostic is issued and false is returned after recovery.
+ ///
+ /// If the input is malformed, this emits the specified diagnostic and true is
+ /// returned.
+ bool ExpectAndConsume(tok::TokenKind ExpectedTok,
+ unsigned Diag = diag::err_expected,
+ StringRef DiagMsg = "");
+
+ /// The parser expects a semicolon and, if present, will consume it.
+ ///
+ /// If the next token is not a semicolon, this emits the specified diagnostic,
+ /// or, if there's just some closing-delimiter noise (e.g., ')' or ']') prior
+ /// to the semicolon, consumes that extra token.
+ bool ExpectAndConsumeSemi(unsigned DiagID);
+
+ /// The kind of extra semi diagnostic to emit.
+ enum ExtraSemiKind {
+ OutsideFunction = 0,
+ InsideStruct = 1,
+ InstanceVariableList = 2,
+ AfterMemberFunctionDefinition = 3
+ };
+
+ /// Consume any extra semi-colons until the end of the line.
+ void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified);
+
+ /// Return false if the next token is an identifier. An 'expected identifier'
+ /// error is emitted otherwise.
+ ///
+ /// The parser tries to recover from the error by checking if the next token
+ /// is a C++ keyword when parsing Objective-C++. Return false if the recovery
+ /// was successful.
+ bool expectIdentifier();
+
+public:
+ //===--------------------------------------------------------------------===//
+ // Scope manipulation
+
+ /// ParseScope - Introduces a new scope for parsing. The kind of
+ /// scope is determined by ScopeFlags. Objects of this type should
+ /// be created on the stack to coincide with the position where the
+ /// parser enters the new scope, and this object's constructor will
+ /// create that new scope. Similarly, once the object is destroyed
+ /// the parser will exit the scope.
+ class ParseScope {
+ Parser *Self;
+ ParseScope(const ParseScope &) = delete;
+ void operator=(const ParseScope &) = delete;
+
+ public:
+ // ParseScope - Construct a new object to manage a scope in the
+ // parser Self where the new Scope is created with the flags
+ // ScopeFlags, but only when we aren't about to enter a compound statement.
+ ParseScope(Parser *Self, unsigned ScopeFlags, bool EnteredScope = true,
+ bool BeforeCompoundStmt = false)
+ : Self(Self) {
+ if (EnteredScope && !BeforeCompoundStmt)
+ Self->EnterScope(ScopeFlags);
+ else {
+ if (BeforeCompoundStmt)
+ Self->incrementMSManglingNumber();
+
+ this->Self = nullptr;
+ }
+ }
+
+ // Exit - Exit the scope associated with this object now, rather
+ // than waiting until the object is destroyed.
+ void Exit() {
+ if (Self) {
+ Self->ExitScope();
+ Self = nullptr;
+ }
+ }
+
+ ~ParseScope() {
+ Exit();
+ }
+ };
+
+ /// EnterScope - Start a new scope.
+ void EnterScope(unsigned ScopeFlags);
+
+ /// ExitScope - Pop a scope off the scope stack.
+ void ExitScope();
+
+private:
+ /// RAII object used to modify the scope flags for the current scope.
+ class ParseScopeFlags {
+ Scope *CurScope;
+ unsigned OldFlags;
+ ParseScopeFlags(const ParseScopeFlags &) = delete;
+ void operator=(const ParseScopeFlags &) = delete;
+
+ public:
+ ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags = true);
+ ~ParseScopeFlags();
+ };
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic Emission and Error recovery.
+
+public:
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID);
+ DiagnosticBuilder Diag(unsigned DiagID) {
+ return Diag(Tok, DiagID);
+ }
+
+private:
+ void SuggestParentheses(SourceLocation Loc, unsigned DK,
+ SourceRange ParenRange);
+ void CheckNestedObjCContexts(SourceLocation AtLoc);
+
+public:
+
+ /// Control flags for SkipUntil functions.
+ enum SkipUntilFlags {
+ StopAtSemi = 1 << 0, ///< Stop skipping at semicolon
+ /// Stop skipping at specified token, but don't skip the token itself
+ StopBeforeMatch = 1 << 1,
+ StopAtCodeCompletion = 1 << 2 ///< Stop at code completion
+ };
+
+ friend constexpr SkipUntilFlags operator|(SkipUntilFlags L,
+ SkipUntilFlags R) {
+ return static_cast<SkipUntilFlags>(static_cast<unsigned>(L) |
+ static_cast<unsigned>(R));
+ }
+
+ /// SkipUntil - Read tokens until we get to the specified token, then consume
+ /// it (unless StopBeforeMatch is specified). Because we cannot guarantee
+ /// that the token will ever occur, this skips to the next token, or to some
+ /// likely good stopping point. If Flags has StopAtSemi flag, skipping will
+ /// stop at a ';' character.
+ ///
+ /// If SkipUntil finds the specified token, it returns true, otherwise it
+ /// returns false.
+ bool SkipUntil(tok::TokenKind T,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
+ return SkipUntil(llvm::makeArrayRef(T), Flags);
+ }
+ bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
+ tok::TokenKind TokArray[] = {T1, T2};
+ return SkipUntil(TokArray, Flags);
+ }
+ bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, tok::TokenKind T3,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
+ tok::TokenKind TokArray[] = {T1, T2, T3};
+ return SkipUntil(TokArray, Flags);
+ }
+ bool SkipUntil(ArrayRef<tok::TokenKind> Toks,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0));
+
+ /// SkipMalformedDecl - Read tokens until we get to some likely good stopping
+ /// point for skipping past a simple-declaration.
+ void SkipMalformedDecl();
+
+private:
+ //===--------------------------------------------------------------------===//
+ // Lexing and parsing of C++ inline methods.
+
+ struct ParsingClass;
+
+ /// [class.mem]p1: "... the class is regarded as complete within
+ /// - function bodies
+ /// - default arguments
+ /// - exception-specifications (TODO: C++0x)
+ /// - and brace-or-equal-initializers for non-static data members
+ /// (including such things in nested classes)."
+ /// LateParsedDeclarations build the tree of those elements so they can
+ /// be parsed after parsing the top-level class.
+ class LateParsedDeclaration {
+ public:
+ virtual ~LateParsedDeclaration();
+
+ virtual void ParseLexedMethodDeclarations();
+ virtual void ParseLexedMemberInitializers();
+ virtual void ParseLexedMethodDefs();
+ virtual void ParseLexedAttributes();
+ };
+
+ /// Inner node of the LateParsedDeclaration tree that parses
+ /// all its members recursively.
+ class LateParsedClass : public LateParsedDeclaration {
+ public:
+ LateParsedClass(Parser *P, ParsingClass *C);
+ ~LateParsedClass() override;
+
+ void ParseLexedMethodDeclarations() override;
+ void ParseLexedMemberInitializers() override;
+ void ParseLexedMethodDefs() override;
+ void ParseLexedAttributes() override;
+
+ private:
+ Parser *Self;
+ ParsingClass *Class;
+ };
+
+ /// Contains the lexed tokens of an attribute with arguments that
+ /// may reference member variables and so need to be parsed at the
+ /// end of the class declaration after parsing all other member
+ /// member declarations.
+ /// FIXME: Perhaps we should change the name of LateParsedDeclaration to
+ /// LateParsedTokens.
+ struct LateParsedAttribute : public LateParsedDeclaration {
+ Parser *Self;
+ CachedTokens Toks;
+ IdentifierInfo &AttrName;
+ SourceLocation AttrNameLoc;
+ SmallVector<Decl*, 2> Decls;
+
+ explicit LateParsedAttribute(Parser *P, IdentifierInfo &Name,
+ SourceLocation Loc)
+ : Self(P), AttrName(Name), AttrNameLoc(Loc) {}
+
+ void ParseLexedAttributes() override;
+
+ void addDecl(Decl *D) { Decls.push_back(D); }
+ };
+
+ // A list of late-parsed attributes. Used by ParseGNUAttributes.
+ class LateParsedAttrList: public SmallVector<LateParsedAttribute *, 2> {
+ public:
+ LateParsedAttrList(bool PSoon = false) : ParseSoon(PSoon) { }
+
+ bool parseSoon() { return ParseSoon; }
+
+ private:
+ bool ParseSoon; // Are we planning to parse these shortly after creation?
+ };
+
+ /// Contains the lexed tokens of a member function definition
+ /// which needs to be parsed at the end of the class declaration
+ /// after parsing all other member declarations.
+ struct LexedMethod : public LateParsedDeclaration {
+ Parser *Self;
+ Decl *D;
+ CachedTokens Toks;
+
+ /// Whether this member function had an associated template
+ /// scope. When true, D is a template declaration.
+ /// otherwise, it is a member function declaration.
+ bool TemplateScope;
+
+ explicit LexedMethod(Parser* P, Decl *MD)
+ : Self(P), D(MD), TemplateScope(false) {}
+
+ void ParseLexedMethodDefs() override;
+ };
+
+ /// LateParsedDefaultArgument - Keeps track of a parameter that may
+ /// have a default argument that cannot be parsed yet because it
+ /// occurs within a member function declaration inside the class
+ /// (C++ [class.mem]p2).
+ struct LateParsedDefaultArgument {
+ explicit LateParsedDefaultArgument(Decl *P,
+ std::unique_ptr<CachedTokens> Toks = nullptr)
+ : Param(P), Toks(std::move(Toks)) { }
+
+ /// Param - The parameter declaration for this parameter.
+ Decl *Param;
+
+ /// Toks - The sequence of tokens that comprises the default
+ /// argument expression, not including the '=' or the terminating
+ /// ')' or ','. This will be NULL for parameters that have no
+ /// default argument.
+ std::unique_ptr<CachedTokens> Toks;
+ };
+
+ /// LateParsedMethodDeclaration - A method declaration inside a class that
+ /// contains at least one entity whose parsing needs to be delayed
+ /// until the class itself is completely-defined, such as a default
+ /// argument (C++ [class.mem]p2).
+ struct LateParsedMethodDeclaration : public LateParsedDeclaration {
+ explicit LateParsedMethodDeclaration(Parser *P, Decl *M)
+ : Self(P), Method(M), TemplateScope(false),
+ ExceptionSpecTokens(nullptr) {}
+
+ void ParseLexedMethodDeclarations() override;
+
+ Parser* Self;
+
+ /// Method - The method declaration.
+ Decl *Method;
+
+ /// Whether this member function had an associated template
+ /// scope. When true, D is a template declaration.
+ /// otherwise, it is a member function declaration.
+ bool TemplateScope;
+
+ /// DefaultArgs - Contains the parameters of the function and
+ /// their default arguments. At least one of the parameters will
+ /// have a default argument, but all of the parameters of the
+ /// method will be stored so that they can be reintroduced into
+ /// scope at the appropriate times.
+ SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
+
+ /// The set of tokens that make up an exception-specification that
+ /// has not yet been parsed.
+ CachedTokens *ExceptionSpecTokens;
+ };
+
+ /// LateParsedMemberInitializer - An initializer for a non-static class data
+ /// member whose parsing must to be delayed until the class is completely
+ /// defined (C++11 [class.mem]p2).
+ struct LateParsedMemberInitializer : public LateParsedDeclaration {
+ LateParsedMemberInitializer(Parser *P, Decl *FD)
+ : Self(P), Field(FD) { }
+
+ void ParseLexedMemberInitializers() override;
+
+ Parser *Self;
+
+ /// Field - The field declaration.
+ Decl *Field;
+
+ /// CachedTokens - The sequence of tokens that comprises the initializer,
+ /// including any leading '='.
+ CachedTokens Toks;
+ };
+
+ /// LateParsedDeclarationsContainer - During parsing of a top (non-nested)
+ /// C++ class, its method declarations that contain parts that won't be
+ /// parsed until after the definition is completed (C++ [class.mem]p2),
+ /// the method declarations and possibly attached inline definitions
+ /// will be stored here with the tokens that will be parsed to create those
+ /// entities.
+ typedef SmallVector<LateParsedDeclaration*,2> LateParsedDeclarationsContainer;
+
+ /// Representation of a class that has been parsed, including
+ /// any member function declarations or definitions that need to be
+ /// parsed after the corresponding top-level class is complete.
+ struct ParsingClass {
+ ParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface)
+ : TopLevelClass(TopLevelClass), TemplateScope(false),
+ IsInterface(IsInterface), TagOrTemplate(TagOrTemplate) { }
+
+ /// Whether this is a "top-level" class, meaning that it is
+ /// not nested within another class.
+ bool TopLevelClass : 1;
+
+ /// Whether this class had an associated template
+ /// scope. When true, TagOrTemplate is a template declaration;
+ /// otherwise, it is a tag declaration.
+ bool TemplateScope : 1;
+
+ /// Whether this class is an __interface.
+ bool IsInterface : 1;
+
+ /// The class or class template whose definition we are parsing.
+ Decl *TagOrTemplate;
+
+ /// LateParsedDeclarations - Method declarations, inline definitions and
+ /// nested classes that contain pieces whose parsing will be delayed until
+ /// the top-level class is fully defined.
+ LateParsedDeclarationsContainer LateParsedDeclarations;
+ };
+
+ /// The stack of classes that is currently being
+ /// parsed. Nested and local classes will be pushed onto this stack
+ /// when they are parsed, and removed afterward.
+ std::stack<ParsingClass *> ClassStack;
+
+ ParsingClass &getCurrentClass() {
+ assert(!ClassStack.empty() && "No lexed method stacks!");
+ return *ClassStack.top();
+ }
+
+ /// RAII object used to manage the parsing of a class definition.
+ class ParsingClassDefinition {
+ Parser &P;
+ bool Popped;
+ Sema::ParsingClassState State;
+
+ public:
+ ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass,
+ bool IsInterface)
+ : P(P), Popped(false),
+ State(P.PushParsingClass(TagOrTemplate, TopLevelClass, IsInterface)) {
+ }
+
+ /// Pop this class of the stack.
+ void Pop() {
+ assert(!Popped && "Nested class has already been popped");
+ Popped = true;
+ P.PopParsingClass(State);
+ }
+
+ ~ParsingClassDefinition() {
+ if (!Popped)
+ P.PopParsingClass(State);
+ }
+ };
+
+ /// Contains information about any template-specific
+ /// information that has been parsed prior to parsing declaration
+ /// specifiers.
+ struct ParsedTemplateInfo {
+ ParsedTemplateInfo()
+ : Kind(NonTemplate), TemplateParams(nullptr), TemplateLoc() { }
+
+ ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
+ bool isSpecialization,
+ bool lastParameterListWasEmpty = false)
+ : Kind(isSpecialization? ExplicitSpecialization : Template),
+ TemplateParams(TemplateParams),
+ LastParameterListWasEmpty(lastParameterListWasEmpty) { }
+
+ explicit ParsedTemplateInfo(SourceLocation ExternLoc,
+ SourceLocation TemplateLoc)
+ : Kind(ExplicitInstantiation), TemplateParams(nullptr),
+ ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
+ LastParameterListWasEmpty(false){ }
+
+ /// The kind of template we are parsing.
+ enum {
+ /// We are not parsing a template at all.
+ NonTemplate = 0,
+ /// We are parsing a template declaration.
+ Template,
+ /// We are parsing an explicit specialization.
+ ExplicitSpecialization,
+ /// We are parsing an explicit instantiation.
+ ExplicitInstantiation
+ } Kind;
+
+ /// The template parameter lists, for template declarations
+ /// and explicit specializations.
+ TemplateParameterLists *TemplateParams;
+
+ /// The location of the 'extern' keyword, if any, for an explicit
+ /// instantiation
+ SourceLocation ExternLoc;
+
+ /// The location of the 'template' keyword, for an explicit
+ /// instantiation.
+ SourceLocation TemplateLoc;
+
+ /// Whether the last template parameter list was empty.
+ bool LastParameterListWasEmpty;
+
+ SourceRange getSourceRange() const LLVM_READONLY;
+ };
+
+ void LexTemplateFunctionForLateParsing(CachedTokens &Toks);
+ void ParseLateTemplatedFuncDef(LateParsedTemplate &LPT);
+
+ static void LateTemplateParserCallback(void *P, LateParsedTemplate &LPT);
+ static void LateTemplateParserCleanupCallback(void *P);
+
+ Sema::ParsingClassState
+ PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface);
+ void DeallocateParsedClasses(ParsingClass *Class);
+ void PopParsingClass(Sema::ParsingClassState);
+
+ enum CachedInitKind {
+ CIK_DefaultArgument,
+ CIK_DefaultInitializer
+ };
+
+ NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS,
+ ParsedAttributes &AccessAttrs,
+ ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo,
+ const VirtSpecifiers &VS,
+ SourceLocation PureSpecLoc);
+ void ParseCXXNonStaticMemberInitializer(Decl *VarD);
+ void ParseLexedAttributes(ParsingClass &Class);
+ void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
+ bool EnterScope, bool OnDefinition);
+ void ParseLexedAttribute(LateParsedAttribute &LA,
+ bool EnterScope, bool OnDefinition);
+ void ParseLexedMethodDeclarations(ParsingClass &Class);
+ void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
+ void ParseLexedMethodDefs(ParsingClass &Class);
+ void ParseLexedMethodDef(LexedMethod &LM);
+ void ParseLexedMemberInitializers(ParsingClass &Class);
+ void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
+ void ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod);
+ bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks);
+ bool ConsumeAndStoreInitializer(CachedTokens &Toks, CachedInitKind CIK);
+ bool ConsumeAndStoreConditional(CachedTokens &Toks);
+ bool ConsumeAndStoreUntil(tok::TokenKind T1,
+ CachedTokens &Toks,
+ bool StopAtSemi = true,
+ bool ConsumeFinalToken = true) {
+ return ConsumeAndStoreUntil(T1, T1, Toks, StopAtSemi, ConsumeFinalToken);
+ }
+ bool ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
+ CachedTokens &Toks,
+ bool StopAtSemi = true,
+ bool ConsumeFinalToken = true);
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.9: External Definitions.
+ struct ParsedAttributesWithRange : ParsedAttributes {
+ ParsedAttributesWithRange(AttributeFactory &factory)
+ : ParsedAttributes(factory) {}
+
+ void clear() {
+ ParsedAttributes::clear();
+ Range = SourceRange();
+ }
+
+ SourceRange Range;
+ };
+ struct ParsedAttributesViewWithRange : ParsedAttributesView {
+ ParsedAttributesViewWithRange() : ParsedAttributesView() {}
+ void clearListOnly() {
+ ParsedAttributesView::clearListOnly();
+ Range = SourceRange();
+ }
+
+ SourceRange Range;
+ };
+
+ DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS = nullptr);
+ bool isDeclarationAfterDeclarator();
+ bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
+ ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS = nullptr,
+ AccessSpecifier AS = AS_none);
+ DeclGroupPtrTy ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec &DS,
+ AccessSpecifier AS);
+
+ void SkipFunctionBody();
+ Decl *ParseFunctionDefinition(ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ LateParsedAttrList *LateParsedAttrs = nullptr);
+ void ParseKNRParamDeclarations(Declarator &D);
+ // EndLoc, if non-NULL, is filled with the location of the last token of
+ // the simple-asm.
+ ExprResult ParseSimpleAsm(SourceLocation *EndLoc = nullptr);
+ ExprResult ParseAsmStringLiteral();
+
+ // Objective-C External Declarations
+ void MaybeSkipAttributes(tok::ObjCKeywordKind Kind);
+ DeclGroupPtrTy ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs);
+ DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
+ ParsedAttributes &prefixAttrs);
+ class ObjCTypeParamListScope;
+ ObjCTypeParamList *parseObjCTypeParamList();
+ ObjCTypeParamList *parseObjCTypeParamListOrProtocolRefs(
+ ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc,
+ SmallVectorImpl<IdentifierLocPair> &protocolIdents,
+ SourceLocation &rAngleLoc, bool mayBeProtocolList = true);
+
+ void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
+ BalancedDelimiterTracker &T,
+ SmallVectorImpl<Decl *> &AllIvarDecls,
+ bool RBraceMissing);
+ void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
+ tok::ObjCKeywordKind visibility,
+ SourceLocation atLoc);
+ bool ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &P,
+ SmallVectorImpl<SourceLocation> &PLocs,
+ bool WarnOnDeclarations,
+ bool ForObjCContainer,
+ SourceLocation &LAngleLoc,
+ SourceLocation &EndProtoLoc,
+ bool consumeLastToken);
+
+ /// Parse the first angle-bracket-delimited clause for an
+ /// Objective-C object or object pointer type, which may be either
+ /// type arguments or protocol qualifiers.
+ void parseObjCTypeArgsOrProtocolQualifiers(
+ ParsedType baseType,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SmallVectorImpl<SourceLocation> &protocolLocs,
+ SourceLocation &protocolRAngleLoc,
+ bool consumeLastToken,
+ bool warnOnIncompleteProtocols);
+
+ /// Parse either Objective-C type arguments or protocol qualifiers; if the
+ /// former, also parse protocol qualifiers afterward.
+ void parseObjCTypeArgsAndProtocolQualifiers(
+ ParsedType baseType,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SmallVectorImpl<SourceLocation> &protocolLocs,
+ SourceLocation &protocolRAngleLoc,
+ bool consumeLastToken);
+
+ /// Parse a protocol qualifier type such as '<NSCopying>', which is
+ /// an anachronistic way of writing 'id<NSCopying>'.
+ TypeResult parseObjCProtocolQualifierType(SourceLocation &rAngleLoc);
+
+ /// Parse Objective-C type arguments and protocol qualifiers, extending the
+ /// current type with the parsed result.
+ TypeResult parseObjCTypeArgsAndProtocolQualifiers(SourceLocation loc,
+ ParsedType type,
+ bool consumeLastToken,
+ SourceLocation &endLoc);
+
+ void ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
+ Decl *CDecl);
+ DeclGroupPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
+ ParsedAttributes &prefixAttrs);
+
+ struct ObjCImplParsingDataRAII {
+ Parser &P;
+ Decl *Dcl;
+ bool HasCFunction;
+ typedef SmallVector<LexedMethod*, 8> LateParsedObjCMethodContainer;
+ LateParsedObjCMethodContainer LateParsedObjCMethods;
+
+ ObjCImplParsingDataRAII(Parser &parser, Decl *D)
+ : P(parser), Dcl(D), HasCFunction(false) {
+ P.CurParsedObjCImpl = this;
+ Finished = false;
+ }
+ ~ObjCImplParsingDataRAII();
+
+ void finish(SourceRange AtEnd);
+ bool isFinished() const { return Finished; }
+
+ private:
+ bool Finished;
+ };
+ ObjCImplParsingDataRAII *CurParsedObjCImpl;
+ void StashAwayMethodOrFunctionBodyTokens(Decl *MDecl);
+
+ DeclGroupPtrTy ParseObjCAtImplementationDeclaration(SourceLocation AtLoc);
+ DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);
+ Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCPropertySynthesize(SourceLocation atLoc);
+ Decl *ParseObjCPropertyDynamic(SourceLocation atLoc);
+
+ IdentifierInfo *ParseObjCSelectorPiece(SourceLocation &MethodLocation);
+ // Definitions for Objective-c context sensitive keywords recognition.
+ enum ObjCTypeQual {
+ objc_in=0, objc_out, objc_inout, objc_oneway, objc_bycopy, objc_byref,
+ objc_nonnull, objc_nullable, objc_null_unspecified,
+ objc_NumQuals
+ };
+ IdentifierInfo *ObjCTypeQuals[objc_NumQuals];
+
+ bool isTokIdentifier_in() const;
+
+ ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, DeclaratorContext Ctx,
+ ParsedAttributes *ParamAttrs);
+ void ParseObjCMethodRequirement();
+ Decl *ParseObjCMethodPrototype(
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword,
+ bool MethodDefinition = true);
+ Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword,
+ bool MethodDefinition=true);
+ void ParseObjCPropertyAttribute(ObjCDeclSpec &DS);
+
+ Decl *ParseObjCMethodDefinition();
+
+public:
+ //===--------------------------------------------------------------------===//
+ // C99 6.5: Expressions.
+
+ /// TypeCastState - State whether an expression is or may be a type cast.
+ enum TypeCastState {
+ NotTypeCast = 0,
+ MaybeTypeCast,
+ IsTypeCast
+ };
+
+ ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast);
+ ExprResult ParseConstantExpressionInExprEvalContext(
+ TypeCastState isTypeCast = NotTypeCast);
+ ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast);
+ ExprResult ParseCaseExpression(SourceLocation CaseLoc);
+ ExprResult ParseConstraintExpression();
+ // Expr that doesn't include commas.
+ ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast);
+
+ ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
+ unsigned &NumLineToksConsumed,
+ bool IsUnevaluated);
+
+private:
+ ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc);
+
+ ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc);
+
+ ExprResult ParseRHSOfBinaryExpression(ExprResult LHS,
+ prec::Level MinPrec);
+ ExprResult ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand,
+ bool &NotCastExpr,
+ TypeCastState isTypeCast,
+ bool isVectorLiteral = false);
+ ExprResult ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand = false,
+ TypeCastState isTypeCast = NotTypeCast,
+ bool isVectorLiteral = false);
+
+ /// Returns true if the next token cannot start an expression.
+ bool isNotExpressionStart();
+
+ /// Returns true if the next token would start a postfix-expression
+ /// suffix.
+ bool isPostfixExpressionSuffixStart() {
+ tok::TokenKind K = Tok.getKind();
+ return (K == tok::l_square || K == tok::l_paren ||
+ K == tok::period || K == tok::arrow ||
+ K == tok::plusplus || K == tok::minusminus);
+ }
+
+ bool diagnoseUnknownTemplateId(ExprResult TemplateName, SourceLocation Less);
+ void checkPotentialAngleBracket(ExprResult &PotentialTemplateName);
+ bool checkPotentialAngleBracketDelimiter(const AngleBracketTracker::Loc &,
+ const Token &OpToken);
+ bool checkPotentialAngleBracketDelimiter(const Token &OpToken) {
+ if (auto *Info = AngleBrackets.getCurrent(*this))
+ return checkPotentialAngleBracketDelimiter(*Info, OpToken);
+ return false;
+ }
+
+ ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
+ ExprResult ParseUnaryExprOrTypeTraitExpression();
+ ExprResult ParseBuiltinPrimaryExpression();
+
+ ExprResult ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
+ bool &isCastExpr,
+ ParsedType &CastTy,
+ SourceRange &CastRange);
+
+ typedef SmallVector<Expr*, 20> ExprListTy;
+ typedef SmallVector<SourceLocation, 20> CommaLocsTy;
+
+ /// ParseExpressionList - Used for C/C++ (argument-)expression-list.
+ bool ParseExpressionList(
+ SmallVectorImpl<Expr *> &Exprs,
+ SmallVectorImpl<SourceLocation> &CommaLocs,
+ llvm::function_ref<void()> Completer = llvm::function_ref<void()>());
+
+ /// ParseSimpleExpressionList - A simple comma-separated list of expressions,
+ /// used for misc language extensions.
+ bool ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs,
+ SmallVectorImpl<SourceLocation> &CommaLocs);
+
+
+ /// ParenParseOption - Control what ParseParenExpression will parse.
+ enum ParenParseOption {
+ SimpleExpr, // Only parse '(' expression ')'
+ FoldExpr, // Also allow fold-expression <anything>
+ CompoundStmt, // Also allow '(' compound-statement ')'
+ CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
+ CastExpr // Also allow '(' type-name ')' <anything>
+ };
+ ExprResult ParseParenExpression(ParenParseOption &ExprType,
+ bool stopIfCastExpr,
+ bool isTypeCast,
+ ParsedType &CastTy,
+ SourceLocation &RParenLoc);
+
+ ExprResult ParseCXXAmbiguousParenExpression(
+ ParenParseOption &ExprType, ParsedType &CastTy,
+ BalancedDelimiterTracker &Tracker, ColonProtectionRAIIObject &ColonProt);
+ ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral = false);
+
+ ExprResult ParseGenericSelectionExpression();
+
+ ExprResult ParseObjCBoolLiteral();
+
+ ExprResult ParseFoldExpression(ExprResult LHS, BalancedDelimiterTracker &T);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Expressions
+ ExprResult tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOperand,
+ Token &Replacement);
+ ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
+
+ bool areTokensAdjacent(const Token &A, const Token &B);
+
+ void CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectTypePtr,
+ bool EnteringContext, IdentifierInfo &II,
+ CXXScopeSpec &SS);
+
+ bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ bool *MayBePseudoDestructor = nullptr,
+ bool IsTypename = false,
+ IdentifierInfo **LastII = nullptr,
+ bool OnlyNamespace = false);
+
+ //===--------------------------------------------------------------------===//
+ // C++0x 5.1.2: Lambda expressions
+
+ // [...] () -> type {...}
+ ExprResult ParseLambdaExpression();
+ ExprResult TryParseLambdaExpression();
+ Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro,
+ bool *SkippedInits = nullptr);
+ bool TryParseLambdaIntroducer(LambdaIntroducer &Intro);
+ ExprResult ParseLambdaExpressionAfterIntroducer(
+ LambdaIntroducer &Intro);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2p1: C++ Casts
+ ExprResult ParseCXXCasts();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2p1: C++ Type Identification
+ ExprResult ParseCXXTypeid();
+
+ //===--------------------------------------------------------------------===//
+ // C++ : Microsoft __uuidof Expression
+ ExprResult ParseCXXUuidof();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2.4: C++ Pseudo-Destructor Expressions
+ ExprResult ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ ParsedType ObjectType);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 9.3.2: C++ 'this' pointer
+ ExprResult ParseCXXThis();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 15: C++ Throw Expression
+ ExprResult ParseThrowExpression();
+
+ ExceptionSpecificationType tryParseExceptionSpecification(
+ bool Delayed,
+ SourceRange &SpecificationRange,
+ SmallVectorImpl<ParsedType> &DynamicExceptions,
+ SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
+ ExprResult &NoexceptExpr,
+ CachedTokens *&ExceptionSpecTokens);
+
+ // EndLoc is filled with the location of the last token of the specification.
+ ExceptionSpecificationType ParseDynamicExceptionSpecification(
+ SourceRange &SpecificationRange,
+ SmallVectorImpl<ParsedType> &Exceptions,
+ SmallVectorImpl<SourceRange> &Ranges);
+
+ //===--------------------------------------------------------------------===//
+ // C++0x 8: Function declaration trailing-return-type
+ TypeResult ParseTrailingReturnType(SourceRange &Range,
+ bool MayBeFollowedByDirectInit);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 2.13.5: C++ Boolean Literals
+ ExprResult ParseCXXBoolLiteral();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2.3: Explicit type conversion (functional notation)
+ ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
+
+ /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
+ /// This should only be called when the current token is known to be part of
+ /// simple-type-specifier.
+ void ParseCXXSimpleTypeSpecifier(DeclSpec &DS);
+
+ bool ParseCXXTypeSpecifierSeq(DeclSpec &DS);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.3.4 and 5.3.5: C++ new and delete
+ bool ParseExpressionListOrTypeId(SmallVectorImpl<Expr*> &Exprs,
+ Declarator &D);
+ void ParseDirectNewDeclarator(Declarator &D);
+ ExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start);
+ ExprResult ParseCXXDeleteExpression(bool UseGlobal,
+ SourceLocation Start);
+
+ //===--------------------------------------------------------------------===//
+ // C++ if/switch/while/for condition expression.
+ struct ForRangeInfo;
+ Sema::ConditionResult ParseCXXCondition(StmtResult *InitStmt,
+ SourceLocation Loc,
+ Sema::ConditionKind CK,
+ ForRangeInfo *FRI = nullptr);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Coroutines
+
+ ExprResult ParseCoyieldExpression();
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.7.8: Initialization.
+
+ /// ParseInitializer
+ /// initializer: [C99 6.7.8]
+ /// assignment-expression
+ /// '{' ...
+ ExprResult ParseInitializer() {
+ if (Tok.isNot(tok::l_brace))
+ return ParseAssignmentExpression();
+ return ParseBraceInitializer();
+ }
+ bool MayBeDesignationStart();
+ ExprResult ParseBraceInitializer();
+ ExprResult ParseInitializerWithPotentialDesignator();
+
+ //===--------------------------------------------------------------------===//
+ // clang Expressions
+
+ ExprResult ParseBlockLiteralExpression(); // ^{...}
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C Expressions
+ ExprResult ParseObjCAtExpression(SourceLocation AtLocation);
+ ExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCCharacterLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCNumericLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue);
+ ExprResult ParseObjCArrayLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCBoxedExpr(SourceLocation AtLoc);
+ ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
+ bool isSimpleObjCMessageExpression();
+ ExprResult ParseObjCMessageExpression();
+ ExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
+ SourceLocation SuperLoc,
+ ParsedType ReceiverType,
+ Expr *ReceiverExpr);
+ ExprResult ParseAssignmentExprWithObjCMessageExprStart(
+ SourceLocation LBracloc, SourceLocation SuperLoc,
+ ParsedType ReceiverType, Expr *ReceiverExpr);
+ bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr);
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.8: Statements and Blocks.
+
+ /// A SmallVector of statements, with stack size 32 (as that is the only one
+ /// used.)
+ typedef SmallVector<Stmt*, 32> StmtVector;
+ /// A SmallVector of expressions, with stack size 12 (the maximum used.)
+ typedef SmallVector<Expr*, 12> ExprVector;
+ /// A SmallVector of types.
+ typedef SmallVector<ParsedType, 12> TypeVector;
+
+ StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
+ bool AllowOpenMPStandalone = false);
+ enum AllowedConstructsKind {
+ /// Allow any declarations, statements, OpenMP directives.
+ ACK_Any,
+ /// Allow only statements and non-standalone OpenMP directives.
+ ACK_StatementsOpenMPNonStandalone,
+ /// Allow statements and all executable OpenMP directives
+ ACK_StatementsOpenMPAnyExecutable
+ };
+ StmtResult
+ ParseStatementOrDeclaration(StmtVector &Stmts, AllowedConstructsKind Allowed,
+ SourceLocation *TrailingElseLoc = nullptr);
+ StmtResult ParseStatementOrDeclarationAfterAttributes(
+ StmtVector &Stmts,
+ AllowedConstructsKind Allowed,
+ SourceLocation *TrailingElseLoc,
+ ParsedAttributesWithRange &Attrs);
+ StmtResult ParseExprStatement();
+ StmtResult ParseLabeledStatement(ParsedAttributesWithRange &attrs);
+ StmtResult ParseCaseStatement(bool MissingCase = false,
+ ExprResult Expr = ExprResult());
+ StmtResult ParseDefaultStatement();
+ StmtResult ParseCompoundStatement(bool isStmtExpr = false);
+ StmtResult ParseCompoundStatement(bool isStmtExpr,
+ unsigned ScopeFlags);
+ void ParseCompoundStatementLeadingPragmas();
+ bool ConsumeNullStmt(StmtVector &Stmts);
+ StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
+ bool ParseParenExprOrCondition(StmtResult *InitStmt,
+ Sema::ConditionResult &CondResult,
+ SourceLocation Loc,
+ Sema::ConditionKind CK);
+ StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);
+ StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);
+ StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);
+ StmtResult ParseDoStatement();
+ StmtResult ParseForStatement(SourceLocation *TrailingElseLoc);
+ StmtResult ParseGotoStatement();
+ StmtResult ParseContinueStatement();
+ StmtResult ParseBreakStatement();
+ StmtResult ParseReturnStatement();
+ StmtResult ParseAsmStatement(bool &msAsm);
+ StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
+ StmtResult ParsePragmaLoopHint(StmtVector &Stmts,
+ AllowedConstructsKind Allowed,
+ SourceLocation *TrailingElseLoc,
+ ParsedAttributesWithRange &Attrs);
+
+ /// Describes the behavior that should be taken for an __if_exists
+ /// block.
+ enum IfExistsBehavior {
+ /// Parse the block; this code is always used.
+ IEB_Parse,
+ /// Skip the block entirely; this code is never used.
+ IEB_Skip,
+ /// Parse the block as a dependent block, which may be used in
+ /// some template instantiations but not others.
+ IEB_Dependent
+ };
+
+ /// Describes the condition of a Microsoft __if_exists or
+ /// __if_not_exists block.
+ struct IfExistsCondition {
+ /// The location of the initial keyword.
+ SourceLocation KeywordLoc;
+ /// Whether this is an __if_exists block (rather than an
+ /// __if_not_exists block).
+ bool IsIfExists;
+
+ /// Nested-name-specifier preceding the name.
+ CXXScopeSpec SS;
+
+ /// The name we're looking for.
+ UnqualifiedId Name;
+
+ /// The behavior of this __if_exists or __if_not_exists block
+ /// should.
+ IfExistsBehavior Behavior;
+ };
+
+ bool ParseMicrosoftIfExistsCondition(IfExistsCondition& Result);
+ void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
+ void ParseMicrosoftIfExistsExternalDeclaration();
+ void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier &CurAS);
+ bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
+ bool &InitExprsOk);
+ bool ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
+ SmallVectorImpl<Expr *> &Constraints,
+ SmallVectorImpl<Expr *> &Exprs);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 6: Statements and Blocks
+
+ StmtResult ParseCXXTryBlock();
+ StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry = false);
+ StmtResult ParseCXXCatchBlock(bool FnCatch = false);
+
+ //===--------------------------------------------------------------------===//
+ // MS: SEH Statements and Blocks
+
+ StmtResult ParseSEHTryBlock();
+ StmtResult ParseSEHExceptBlock(SourceLocation Loc);
+ StmtResult ParseSEHFinallyBlock(SourceLocation Loc);
+ StmtResult ParseSEHLeaveStatement();
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C Statements
+
+ StmtResult ParseObjCAtStatement(SourceLocation atLoc);
+ StmtResult ParseObjCTryStmt(SourceLocation atLoc);
+ StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
+ StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
+ StmtResult ParseObjCAutoreleasePoolStmt(SourceLocation atLoc);
+
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.7: Declarations.
+
+ /// A context for parsing declaration specifiers. TODO: flesh this
+ /// out, there are other significant restrictions on specifiers than
+ /// would be best implemented in the parser.
+ enum class DeclSpecContext {
+ DSC_normal, // normal context
+ DSC_class, // class context, enables 'friend'
+ DSC_type_specifier, // C++ type-specifier-seq or C specifier-qualifier-list
+ DSC_trailing, // C++11 trailing-type-specifier in a trailing return type
+ DSC_alias_declaration, // C++11 type-specifier-seq in an alias-declaration
+ DSC_top_level, // top-level/namespace declaration context
+ DSC_template_param, // template parameter context
+ DSC_template_type_arg, // template type argument context
+ DSC_objc_method_result, // ObjC method result context, enables 'instancetype'
+ DSC_condition // condition declaration context
+ };
+
+ /// Is this a context in which we are parsing just a type-specifier (or
+ /// trailing-type-specifier)?
+ static bool isTypeSpecifier(DeclSpecContext DSC) {
+ switch (DSC) {
+ case DeclSpecContext::DSC_normal:
+ case DeclSpecContext::DSC_template_param:
+ case DeclSpecContext::DSC_class:
+ case DeclSpecContext::DSC_top_level:
+ case DeclSpecContext::DSC_objc_method_result:
+ case DeclSpecContext::DSC_condition:
+ return false;
+
+ case DeclSpecContext::DSC_template_type_arg:
+ case DeclSpecContext::DSC_type_specifier:
+ case DeclSpecContext::DSC_trailing:
+ case DeclSpecContext::DSC_alias_declaration:
+ return true;
+ }
+ llvm_unreachable("Missing DeclSpecContext case");
+ }
+
+ /// Is this a context in which we can perform class template argument
+ /// deduction?
+ static bool isClassTemplateDeductionContext(DeclSpecContext DSC) {
+ switch (DSC) {
+ case DeclSpecContext::DSC_normal:
+ case DeclSpecContext::DSC_template_param:
+ case DeclSpecContext::DSC_class:
+ case DeclSpecContext::DSC_top_level:
+ case DeclSpecContext::DSC_condition:
+ case DeclSpecContext::DSC_type_specifier:
+ return true;
+
+ case DeclSpecContext::DSC_objc_method_result:
+ case DeclSpecContext::DSC_template_type_arg:
+ case DeclSpecContext::DSC_trailing:
+ case DeclSpecContext::DSC_alias_declaration:
+ return false;
+ }
+ llvm_unreachable("Missing DeclSpecContext case");
+ }
+
+ /// Information on a C++0x for-range-initializer found while parsing a
+ /// declaration which turns out to be a for-range-declaration.
+ struct ForRangeInit {
+ SourceLocation ColonLoc;
+ ExprResult RangeExpr;
+
+ bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); }
+ };
+ struct ForRangeInfo : ForRangeInit {
+ StmtResult LoopVar;
+ };
+
+ DeclGroupPtrTy ParseDeclaration(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs);
+ DeclGroupPtrTy ParseSimpleDeclaration(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs,
+ bool RequireSemi,
+ ForRangeInit *FRI = nullptr);
+ bool MightBeDeclarator(DeclaratorContext Context);
+ DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, DeclaratorContext Context,
+ SourceLocation *DeclEnd = nullptr,
+ ForRangeInit *FRI = nullptr);
+ Decl *ParseDeclarationAfterDeclarator(Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
+ bool ParseAsmAttributesAfterDeclarator(Declarator &D);
+ Decl *ParseDeclarationAfterDeclaratorAndAttributes(
+ Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ForRangeInit *FRI = nullptr);
+ Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope);
+ Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope);
+
+ /// When in code-completion, skip parsing of the function/method body
+ /// unless the body contains the code-completion point.
+ ///
+ /// \returns true if the function body was skipped.
+ bool trySkippingFunctionBody();
+
+ bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS, DeclSpecContext DSC,
+ ParsedAttributesWithRange &Attrs);
+ DeclSpecContext
+ getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context);
+ void ParseDeclarationSpecifiers(
+ DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none,
+ DeclSpecContext DSC = DeclSpecContext::DSC_normal,
+ LateParsedAttrList *LateAttrs = nullptr);
+ bool DiagnoseMissingSemiAfterTagDefinition(
+ DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext,
+ LateParsedAttrList *LateAttrs = nullptr);
+
+ void ParseSpecifierQualifierList(
+ DeclSpec &DS, AccessSpecifier AS = AS_none,
+ DeclSpecContext DSC = DeclSpecContext::DSC_normal);
+
+ void ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
+ DeclaratorContext Context);
+
+ void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS, DeclSpecContext DSC);
+ void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl);
+ void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
+ Decl *TagDecl);
+
+ void ParseStructDeclaration(
+ ParsingDeclSpec &DS,
+ llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback);
+
+ bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false);
+ bool isTypeSpecifierQualifier();
+
+ /// isKnownToBeTypeSpecifier - Return true if we know that the specified token
+ /// is definitely a type-specifier. Return false if it isn't part of a type
+ /// specifier or if we're not sure.
+ bool isKnownToBeTypeSpecifier(const Token &Tok) const;
+
+ /// Return true if we know that we are definitely looking at a
+ /// decl-specifier, and isn't part of an expression such as a function-style
+ /// cast. Return false if it's no a decl-specifier, or we're not sure.
+ bool isKnownToBeDeclarationSpecifier() {
+ if (getLangOpts().CPlusPlus)
+ return isCXXDeclarationSpecifier() == TPResult::True;
+ return isDeclarationSpecifier(true);
+ }
+
+ /// isDeclarationStatement - Disambiguates between a declaration or an
+ /// expression statement, when parsing function bodies.
+ /// Returns true for declaration, false for expression.
+ bool isDeclarationStatement() {
+ if (getLangOpts().CPlusPlus)
+ return isCXXDeclarationStatement();
+ return isDeclarationSpecifier(true);
+ }
+
+ /// isForInitDeclaration - Disambiguates between a declaration or an
+ /// expression in the context of the C 'clause-1' or the C++
+ // 'for-init-statement' part of a 'for' statement.
+ /// Returns true for declaration, false for expression.
+ bool isForInitDeclaration() {
+ if (getLangOpts().OpenMP)
+ Actions.startOpenMPLoop();
+ if (getLangOpts().CPlusPlus)
+ return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/true);
+ return isDeclarationSpecifier(true);
+ }
+
+ /// Determine whether this is a C++1z for-range-identifier.
+ bool isForRangeIdentifier();
+
+ /// Determine whether we are currently at the start of an Objective-C
+ /// class message that appears to be missing the open bracket '['.
+ bool isStartOfObjCClassMessageMissingOpenBracket();
+
+ /// Starting with a scope specifier, identifier, or
+ /// template-id that refers to the current class, determine whether
+ /// this is a constructor declarator.
+ bool isConstructorDeclarator(bool Unqualified, bool DeductionGuide = false);
+
+ /// Specifies the context in which type-id/expression
+ /// disambiguation will occur.
+ enum TentativeCXXTypeIdContext {
+ TypeIdInParens,
+ TypeIdUnambiguous,
+ TypeIdAsTemplateArgument
+ };
+
+
+ /// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know
+ /// whether the parens contain an expression or a type-id.
+ /// Returns true for a type-id and false for an expression.
+ bool isTypeIdInParens(bool &isAmbiguous) {
+ if (getLangOpts().CPlusPlus)
+ return isCXXTypeId(TypeIdInParens, isAmbiguous);
+ isAmbiguous = false;
+ return isTypeSpecifierQualifier();
+ }
+ bool isTypeIdInParens() {
+ bool isAmbiguous;
+ return isTypeIdInParens(isAmbiguous);
+ }
+
+ /// Checks if the current tokens form type-id or expression.
+ /// It is similar to isTypeIdInParens but does not suppose that type-id
+ /// is in parenthesis.
+ bool isTypeIdUnambiguously() {
+ bool IsAmbiguous;
+ if (getLangOpts().CPlusPlus)
+ return isCXXTypeId(TypeIdUnambiguous, IsAmbiguous);
+ return isTypeSpecifierQualifier();
+ }
+
+ /// isCXXDeclarationStatement - C++-specialized function that disambiguates
+ /// between a declaration or an expression statement, when parsing function
+ /// bodies. Returns true for declaration, false for expression.
+ bool isCXXDeclarationStatement();
+
+ /// isCXXSimpleDeclaration - C++-specialized function that disambiguates
+ /// between a simple-declaration or an expression-statement.
+ /// If during the disambiguation process a parsing error is encountered,
+ /// the function returns true to let the declaration parsing code handle it.
+ /// Returns false if the statement is disambiguated as expression.
+ bool isCXXSimpleDeclaration(bool AllowForRangeDecl);
+
+ /// isCXXFunctionDeclarator - Disambiguates between a function declarator or
+ /// a constructor-style initializer, when parsing declaration statements.
+ /// Returns true for function declarator and false for constructor-style
+ /// initializer. Sets 'IsAmbiguous' to true to indicate that this declaration
+ /// might be a constructor-style initializer.
+ /// If during the disambiguation process a parsing error is encountered,
+ /// the function returns true to let the declaration parsing code handle it.
+ bool isCXXFunctionDeclarator(bool *IsAmbiguous = nullptr);
+
+ struct ConditionDeclarationOrInitStatementState;
+ enum class ConditionOrInitStatement {
+ Expression, ///< Disambiguated as an expression (either kind).
+ ConditionDecl, ///< Disambiguated as the declaration form of condition.
+ InitStmtDecl, ///< Disambiguated as a simple-declaration init-statement.
+ ForRangeDecl, ///< Disambiguated as a for-range declaration.
+ Error ///< Can't be any of the above!
+ };
+ /// Disambiguates between the different kinds of things that can happen
+ /// after 'if (' or 'switch ('. This could be one of two different kinds of
+ /// declaration (depending on whether there is a ';' later) or an expression.
+ ConditionOrInitStatement
+ isCXXConditionDeclarationOrInitStatement(bool CanBeInitStmt,
+ bool CanBeForRangeDecl);
+
+ bool isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous);
+ bool isCXXTypeId(TentativeCXXTypeIdContext Context) {
+ bool isAmbiguous;
+ return isCXXTypeId(Context, isAmbiguous);
+ }
+
+ /// TPResult - Used as the result value for functions whose purpose is to
+ /// disambiguate C++ constructs by "tentatively parsing" them.
+ enum class TPResult {
+ True, False, Ambiguous, Error
+ };
+
+ /// Based only on the given token kind, determine whether we know that
+ /// we're at the start of an expression or a type-specifier-seq (which may
+ /// be an expression, in C++).
+ ///
+ /// This routine does not attempt to resolve any of the trick cases, e.g.,
+ /// those involving lookup of identifiers.
+ ///
+ /// \returns \c TPR_true if this token starts an expression, \c TPR_false if
+ /// this token starts a type-specifier-seq, or \c TPR_ambiguous if it cannot
+ /// tell.
+ TPResult isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind);
+
+ /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a
+ /// declaration specifier, TPResult::False if it is not,
+ /// TPResult::Ambiguous if it could be either a decl-specifier or a
+ /// function-style cast, and TPResult::Error if a parsing error was
+ /// encountered. If it could be a braced C++11 function-style cast, returns
+ /// BracedCastResult.
+ /// Doesn't consume tokens.
+ TPResult
+ isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False,
+ bool *HasMissingTypename = nullptr);
+
+ /// Given that isCXXDeclarationSpecifier returns \c TPResult::True or
+ /// \c TPResult::Ambiguous, determine whether the decl-specifier would be
+ /// a type-specifier other than a cv-qualifier.
+ bool isCXXDeclarationSpecifierAType();
+
+ /// Determine whether an identifier has been tentatively declared as a
+ /// non-type. Such tentative declarations should not be found to name a type
+ /// during a tentative parse, but also should not be annotated as a non-type.
+ bool isTentativelyDeclared(IdentifierInfo *II);
+
+ // "Tentative parsing" functions, used for disambiguation. If a parsing error
+ // is encountered they will return TPResult::Error.
+ // Returning TPResult::True/False indicates that the ambiguity was
+ // resolved and tentative parsing may stop. TPResult::Ambiguous indicates
+ // that more tentative parsing is necessary for disambiguation.
+ // They all consume tokens, so backtracking should be used after calling them.
+
+ TPResult TryParseSimpleDeclaration(bool AllowForRangeDecl);
+ TPResult TryParseTypeofSpecifier();
+ TPResult TryParseProtocolQualifiers();
+ TPResult TryParsePtrOperatorSeq();
+ TPResult TryParseOperatorId();
+ TPResult TryParseInitDeclaratorList();
+ TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier = true,
+ bool mayHaveDirectInit = false);
+ TPResult
+ TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = nullptr,
+ bool VersusTemplateArg = false);
+ TPResult TryParseFunctionDeclarator();
+ TPResult TryParseBracketDeclarator();
+ TPResult TryConsumeDeclarationSpecifier();
+
+public:
+ TypeResult ParseTypeName(SourceRange *Range = nullptr,
+ DeclaratorContext Context
+ = DeclaratorContext::TypeNameContext,
+ AccessSpecifier AS = AS_none,
+ Decl **OwnedType = nullptr,
+ ParsedAttributes *Attrs = nullptr);
+
+private:
+ void ParseBlockId(SourceLocation CaretLoc);
+
+ /// Are [[]] attributes enabled?
+ bool standardAttributesAllowed() const {
+ const LangOptions &LO = getLangOpts();
+ return LO.DoubleSquareBracketAttributes;
+ }
+
+ // Check for the start of an attribute-specifier-seq in a context where an
+ // attribute is not allowed.
+ bool CheckProhibitedCXX11Attribute() {
+ assert(Tok.is(tok::l_square));
+ if (!standardAttributesAllowed() || NextToken().isNot(tok::l_square))
+ return false;
+ return DiagnoseProhibitedCXX11Attribute();
+ }
+
+ bool DiagnoseProhibitedCXX11Attribute();
+ void CheckMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
+ SourceLocation CorrectLocation) {
+ if (!standardAttributesAllowed())
+ return;
+ if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) &&
+ Tok.isNot(tok::kw_alignas))
+ return;
+ DiagnoseMisplacedCXX11Attribute(Attrs, CorrectLocation);
+ }
+ void DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
+ SourceLocation CorrectLocation);
+
+ void stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
+ DeclSpec &DS, Sema::TagUseKind TUK);
+
+ // FixItLoc = possible correct location for the attributes
+ void ProhibitAttributes(ParsedAttributesWithRange &Attrs,
+ SourceLocation FixItLoc = SourceLocation()) {
+ if (Attrs.Range.isInvalid())
+ return;
+ DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc);
+ Attrs.clear();
+ }
+
+ void ProhibitAttributes(ParsedAttributesViewWithRange &Attrs,
+ SourceLocation FixItLoc = SourceLocation()) {
+ if (Attrs.Range.isInvalid())
+ return;
+ DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc);
+ Attrs.clearListOnly();
+ }
+ void DiagnoseProhibitedAttributes(const SourceRange &Range,
+ SourceLocation FixItLoc);
+
+ // Forbid C++11 and C2x attributes that appear on certain syntactic locations
+ // which standard permits but we don't supported yet, for example, attributes
+ // appertain to decl specifiers.
+ void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
+ unsigned DiagID);
+
+ /// Skip C++11 and C2x attributes and return the end location of the
+ /// last one.
+ /// \returns SourceLocation() if there are no attributes.
+ SourceLocation SkipCXX11Attributes();
+
+ /// Diagnose and skip C++11 and C2x attributes that appear in syntactic
+ /// locations where attributes are not allowed.
+ void DiagnoseAndSkipCXX11Attributes();
+
+ /// Parses syntax-generic attribute arguments for attributes which are
+ /// known to the implementation, and adds them to the given ParsedAttributes
+ /// list with the given attribute syntax. Returns the number of arguments
+ /// parsed for the attribute.
+ unsigned
+ ParseAttributeArgsCommon(IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ ParsedAttr::Syntax Syntax);
+
+ void MaybeParseGNUAttributes(Declarator &D,
+ LateParsedAttrList *LateAttrs = nullptr) {
+ if (Tok.is(tok::kw___attribute)) {
+ ParsedAttributes attrs(AttrFactory);
+ SourceLocation endLoc;
+ ParseGNUAttributes(attrs, &endLoc, LateAttrs, &D);
+ D.takeAttributes(attrs, endLoc);
+ }
+ }
+ void MaybeParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr,
+ LateParsedAttrList *LateAttrs = nullptr) {
+ if (Tok.is(tok::kw___attribute))
+ ParseGNUAttributes(attrs, endLoc, LateAttrs);
+ }
+ void ParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr,
+ LateParsedAttrList *LateAttrs = nullptr,
+ Declarator *D = nullptr);
+ void ParseGNUAttributeArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ ParsedAttr::Syntax Syntax, Declarator *D);
+ IdentifierLoc *ParseIdentifierLoc();
+
+ unsigned
+ ParseClangAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ ParsedAttr::Syntax Syntax);
+
+ void MaybeParseCXX11Attributes(Declarator &D) {
+ if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
+ ParsedAttributesWithRange attrs(AttrFactory);
+ SourceLocation endLoc;
+ ParseCXX11Attributes(attrs, &endLoc);
+ D.takeAttributes(attrs, endLoc);
+ }
+ }
+ void MaybeParseCXX11Attributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr) {
+ if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
+ ParsedAttributesWithRange attrsWithRange(AttrFactory);
+ ParseCXX11Attributes(attrsWithRange, endLoc);
+ attrs.takeAllFrom(attrsWithRange);
+ }
+ }
+ void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *endLoc = nullptr,
+ bool OuterMightBeMessageSend = false) {
+ if (standardAttributesAllowed() &&
+ isCXX11AttributeSpecifier(false, OuterMightBeMessageSend))
+ ParseCXX11Attributes(attrs, endLoc);
+ }
+
+ void ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
+ SourceLocation *EndLoc = nullptr);
+ void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *EndLoc = nullptr);
+ /// Parses a C++11 (or C2x)-style attribute argument list. Returns true
+ /// if this results in adding an attribute to the ParsedAttributes list.
+ bool ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc);
+
+ IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc);
+
+ void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr) {
+ if (getLangOpts().MicrosoftExt && Tok.is(tok::l_square))
+ ParseMicrosoftAttributes(attrs, endLoc);
+ }
+ void ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs);
+ void ParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr);
+ void MaybeParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
+ SourceLocation *End = nullptr) {
+ const auto &LO = getLangOpts();
+ if (LO.DeclSpecKeyword && Tok.is(tok::kw___declspec))
+ ParseMicrosoftDeclSpecs(Attrs, End);
+ }
+ void ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
+ SourceLocation *End = nullptr);
+ bool ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs);
+ void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
+ void DiagnoseAndSkipExtendedMicrosoftTypeAttributes();
+ SourceLocation SkipExtendedMicrosoftTypeAttributes();
+ void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
+ void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
+ void ParseOpenCLKernelAttributes(ParsedAttributes &attrs);
+ void ParseOpenCLQualifiers(ParsedAttributes &Attrs);
+ /// Parses opencl_unroll_hint attribute if language is OpenCL v2.0
+ /// or higher.
+ /// \return false if error happens.
+ bool MaybeParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) {
+ if (getLangOpts().OpenCL)
+ return ParseOpenCLUnrollHintAttribute(Attrs);
+ return true;
+ }
+ /// Parses opencl_unroll_hint attribute.
+ /// \return false if error happens.
+ bool ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs);
+ void ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs);
+
+ VersionTuple ParseVersionTuple(SourceRange &Range);
+ void ParseAvailabilityAttribute(IdentifierInfo &Availability,
+ SourceLocation AvailabilityLoc,
+ ParsedAttributes &attrs,
+ SourceLocation *endLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ ParsedAttr::Syntax Syntax);
+
+ Optional<AvailabilitySpec> ParseAvailabilitySpec();
+ ExprResult ParseAvailabilityCheckExpr(SourceLocation StartLoc);
+
+ void ParseExternalSourceSymbolAttribute(IdentifierInfo &ExternalSourceSymbol,
+ SourceLocation Loc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ ParsedAttr::Syntax Syntax);
+
+ void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
+ SourceLocation ObjCBridgeRelatedLoc,
+ ParsedAttributes &attrs,
+ SourceLocation *endLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ ParsedAttr::Syntax Syntax);
+
+ void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ ParsedAttr::Syntax Syntax);
+
+ void
+ ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
+ SourceLocation AttrNameLoc, ParsedAttributes &Attrs,
+ SourceLocation *EndLoc, IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax);
+
+ void ParseTypeofSpecifier(DeclSpec &DS);
+ SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
+ void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
+ void ParseAtomicSpecifier(DeclSpec &DS);
+
+ ExprResult ParseAlignArgument(SourceLocation Start,
+ SourceLocation &EllipsisLoc);
+ void ParseAlignmentSpecifier(ParsedAttributes &Attrs,
+ SourceLocation *endLoc = nullptr);
+
+ VirtSpecifiers::Specifier isCXX11VirtSpecifier(const Token &Tok) const;
+ VirtSpecifiers::Specifier isCXX11VirtSpecifier() const {
+ return isCXX11VirtSpecifier(Tok);
+ }
+ void ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface,
+ SourceLocation FriendLoc);
+
+ bool isCXX11FinalKeyword() const;
+
+ /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
+ /// enter a new C++ declarator scope and exit it when the function is
+ /// finished.
+ class DeclaratorScopeObj {
+ Parser &P;
+ CXXScopeSpec &SS;
+ bool EnteredScope;
+ bool CreatedScope;
+ public:
+ DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss)
+ : P(p), SS(ss), EnteredScope(false), CreatedScope(false) {}
+
+ void EnterDeclaratorScope() {
+ assert(!EnteredScope && "Already entered the scope!");
+ assert(SS.isSet() && "C++ scope was not set!");
+
+ CreatedScope = true;
+ P.EnterScope(0); // Not a decl scope.
+
+ if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.getCurScope(), SS))
+ EnteredScope = true;
+ }
+
+ ~DeclaratorScopeObj() {
+ if (EnteredScope) {
+ assert(SS.isSet() && "C++ scope was cleared ?");
+ P.Actions.ActOnCXXExitDeclaratorScope(P.getCurScope(), SS);
+ }
+ if (CreatedScope)
+ P.ExitScope();
+ }
+ };
+
+ /// ParseDeclarator - Parse and verify a newly-initialized declarator.
+ void ParseDeclarator(Declarator &D);
+ /// A function that parses a variant of direct-declarator.
+ typedef void (Parser::*DirectDeclParseFunction)(Declarator&);
+ void ParseDeclaratorInternal(Declarator &D,
+ DirectDeclParseFunction DirectDeclParser);
+
+ enum AttrRequirements {
+ AR_NoAttributesParsed = 0, ///< No attributes are diagnosed.
+ AR_GNUAttributesParsedAndRejected = 1 << 0, ///< Diagnose GNU attributes.
+ AR_GNUAttributesParsed = 1 << 1,
+ AR_CXX11AttributesParsed = 1 << 2,
+ AR_DeclspecAttributesParsed = 1 << 3,
+ AR_AllAttributesParsed = AR_GNUAttributesParsed |
+ AR_CXX11AttributesParsed |
+ AR_DeclspecAttributesParsed,
+ AR_VendorAttributesParsed = AR_GNUAttributesParsed |
+ AR_DeclspecAttributesParsed
+ };
+
+ void ParseTypeQualifierListOpt(
+ DeclSpec &DS, unsigned AttrReqs = AR_AllAttributesParsed,
+ bool AtomicAllowed = true, bool IdentifierRequired = false,
+ Optional<llvm::function_ref<void()>> CodeCompletionHandler = None);
+ void ParseDirectDeclarator(Declarator &D);
+ void ParseDecompositionDeclarator(Declarator &D);
+ void ParseParenDeclarator(Declarator &D);
+ void ParseFunctionDeclarator(Declarator &D,
+ ParsedAttributes &attrs,
+ BalancedDelimiterTracker &Tracker,
+ bool IsAmbiguous,
+ bool RequiresArg = false);
+ bool ParseRefQualifier(bool &RefQualifierIsLValueRef,
+ SourceLocation &RefQualifierLoc);
+ bool isFunctionDeclaratorIdentifierList();
+ void ParseFunctionDeclaratorIdentifierList(
+ Declarator &D,
+ SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo);
+ void ParseParameterDeclarationClause(
+ Declarator &D,
+ ParsedAttributes &attrs,
+ SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
+ SourceLocation &EllipsisLoc);
+ void ParseBracketDeclarator(Declarator &D);
+ void ParseMisplacedBracketDeclarator(Declarator &D);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 7: Declarations [dcl.dcl]
+
+ /// The kind of attribute specifier we have found.
+ enum CXX11AttributeKind {
+ /// This is not an attribute specifier.
+ CAK_NotAttributeSpecifier,
+ /// This should be treated as an attribute-specifier.
+ CAK_AttributeSpecifier,
+ /// The next tokens are '[[', but this is not an attribute-specifier. This
+ /// is ill-formed by C++11 [dcl.attr.grammar]p6.
+ CAK_InvalidAttributeSpecifier
+ };
+ CXX11AttributeKind
+ isCXX11AttributeSpecifier(bool Disambiguate = false,
+ bool OuterMightBeMessageSend = false);
+
+ void DiagnoseUnexpectedNamespace(NamedDecl *Context);
+
+ DeclGroupPtrTy ParseNamespace(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
+ SourceLocation InlineLoc = SourceLocation());
+
+ struct InnerNamespaceInfo {
+ SourceLocation NamespaceLoc;
+ SourceLocation InlineLoc;
+ SourceLocation IdentLoc;
+ IdentifierInfo *Ident;
+ };
+ using InnerNamespaceInfoList = llvm::SmallVector<InnerNamespaceInfo, 4>;
+
+ void ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
+ unsigned int index, SourceLocation &InlineLoc,
+ ParsedAttributes &attrs,
+ BalancedDelimiterTracker &Tracker);
+ Decl *ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context);
+ Decl *ParseExportDeclaration();
+ DeclGroupPtrTy ParseUsingDirectiveOrDeclaration(
+ DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs);
+ Decl *ParseUsingDirective(DeclaratorContext Context,
+ SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &attrs);
+
+ struct UsingDeclarator {
+ SourceLocation TypenameLoc;
+ CXXScopeSpec SS;
+ UnqualifiedId Name;
+ SourceLocation EllipsisLoc;
+
+ void clear() {
+ TypenameLoc = EllipsisLoc = SourceLocation();
+ SS.clear();
+ Name.clear();
+ }
+ };
+
+ bool ParseUsingDeclarator(DeclaratorContext Context, UsingDeclarator &D);
+ DeclGroupPtrTy ParseUsingDeclaration(DeclaratorContext Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none);
+ Decl *ParseAliasDeclarationAfterDeclarator(
+ const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
+ UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,
+ ParsedAttributes &Attrs, Decl **OwnedType = nullptr);
+
+ Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
+ Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceLocation &DeclEnd);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 9: classes [class] and C structs/unions.
+ bool isValidAfterTypeSpecifier(bool CouldBeBitfield);
+ void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
+ DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS, bool EnteringContext,
+ DeclSpecContext DSC,
+ ParsedAttributesWithRange &Attributes);
+ void SkipCXXMemberSpecification(SourceLocation StartLoc,
+ SourceLocation AttrFixitLoc,
+ unsigned TagType,
+ Decl *TagDecl);
+ void ParseCXXMemberSpecification(SourceLocation StartLoc,
+ SourceLocation AttrFixitLoc,
+ ParsedAttributesWithRange &Attrs,
+ unsigned TagType,
+ Decl *TagDecl);
+ ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction,
+ SourceLocation &EqualLoc);
+ bool ParseCXXMemberDeclaratorBeforeInitializer(Declarator &DeclaratorInfo,
+ VirtSpecifiers &VS,
+ ExprResult &BitfieldSize,
+ LateParsedAttrList &LateAttrs);
+ void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D,
+ VirtSpecifiers &VS);
+ DeclGroupPtrTy ParseCXXClassMemberDeclaration(
+ AccessSpecifier AS, ParsedAttributes &Attr,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ParsingDeclRAIIObject *DiagsFromTParams = nullptr);
+ DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas(
+ AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
+ DeclSpec::TST TagType, Decl *Tag);
+ void ParseConstructorInitializer(Decl *ConstructorDecl);
+ MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
+ void HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
+ Decl *ThisDecl);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 10: Derived classes [class.derived]
+ TypeResult ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
+ SourceLocation &EndLocation);
+ void ParseBaseClause(Decl *ClassDecl);
+ BaseResult ParseBaseSpecifier(Decl *ClassDecl);
+ AccessSpecifier getAccessSpecifierIfPresent() const;
+
+ bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool EnteringContext,
+ ParsedType ObjectType,
+ UnqualifiedId &Id,
+ bool AssumeTemplateId);
+ bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+ ParsedType ObjectType,
+ UnqualifiedId &Result);
+
+ //===--------------------------------------------------------------------===//
+ // OpenMP: Directives and clauses.
+ /// Parse clauses for '#pragma omp declare simd'.
+ DeclGroupPtrTy ParseOMPDeclareSimdClauses(DeclGroupPtrTy Ptr,
+ CachedTokens &Toks,
+ SourceLocation Loc);
+ /// Parse clauses for '#pragma omp declare target'.
+ DeclGroupPtrTy ParseOMPDeclareTargetClauses();
+ /// Parse '#pragma omp end declare target'.
+ void ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
+ SourceLocation Loc);
+ /// Parses declarative OpenMP directives.
+ DeclGroupPtrTy ParseOpenMPDeclarativeDirectiveWithExtDecl(
+ AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
+ DeclSpec::TST TagType = DeclSpec::TST_unspecified,
+ Decl *TagDecl = nullptr);
+ /// Parse 'omp declare reduction' construct.
+ DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS);
+ /// Parses initializer for provided omp_priv declaration inside the reduction
+ /// initializer.
+ void ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm);
+
+ /// Parses 'omp declare mapper' directive.
+ DeclGroupPtrTy ParseOpenMPDeclareMapperDirective(AccessSpecifier AS);
+ /// Parses variable declaration in 'omp declare mapper' directive.
+ TypeResult parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
+ DeclarationName &Name,
+ AccessSpecifier AS = AS_none);
+
+ /// Parses simple list of variables.
+ ///
+ /// \param Kind Kind of the directive.
+ /// \param Callback Callback function to be called for the list elements.
+ /// \param AllowScopeSpecifier true, if the variables can have fully
+ /// qualified names.
+ ///
+ bool ParseOpenMPSimpleVarList(
+ OpenMPDirectiveKind Kind,
+ const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
+ Callback,
+ bool AllowScopeSpecifier);
+ /// Parses declarative or executable directive.
+ ///
+ /// \param Allowed ACK_Any, if any directives are allowed,
+ /// ACK_StatementsOpenMPAnyExecutable - if any executable directives are
+ /// allowed, ACK_StatementsOpenMPNonStandalone - if only non-standalone
+ /// executable directives are allowed.
+ ///
+ StmtResult
+ ParseOpenMPDeclarativeOrExecutableDirective(AllowedConstructsKind Allowed);
+ /// Parses clause of kind \a CKind for directive of a kind \a Kind.
+ ///
+ /// \param DKind Kind of current directive.
+ /// \param CKind Kind of current clause.
+ /// \param FirstClause true, if this is the first clause of a kind \a CKind
+ /// in current directive.
+ ///
+ OMPClause *ParseOpenMPClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind CKind, bool FirstClause);
+ /// Parses clause with a single expression of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
+ ///
+ OMPClause *ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
+ bool ParseOnly);
+ /// Parses simple clause of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
+ ///
+ OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind, bool ParseOnly);
+ /// Parses clause with a single expression and an additional argument
+ /// of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
+ ///
+ OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
+ bool ParseOnly);
+ /// Parses clause without any additional arguments.
+ ///
+ /// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
+ ///
+ OMPClause *ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly = false);
+ /// Parses clause with the list of variables of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ /// \param ParseOnly true to skip the clause's semantic actions and return
+ /// nullptr.
+ ///
+ OMPClause *ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind Kind, bool ParseOnly);
+
+public:
+ /// Parses simple expression in parens for single-expression clauses of OpenMP
+ /// constructs.
+ /// \param RLoc Returned location of right paren.
+ ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc);
+
+ /// Data used for parsing list of variables in OpenMP clauses.
+ struct OpenMPVarListDataTy {
+ Expr *TailExpr = nullptr;
+ SourceLocation ColonLoc;
+ SourceLocation RLoc;
+ CXXScopeSpec ReductionIdScopeSpec;
+ DeclarationNameInfo ReductionId;
+ OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
+ OpenMPLinearClauseKind LinKind = OMPC_LINEAR_val;
+ SmallVector<OpenMPMapModifierKind, OMPMapClause::NumberOfModifiers>
+ MapTypeModifiers;
+ SmallVector<SourceLocation, OMPMapClause::NumberOfModifiers>
+ MapTypeModifiersLoc;
+ OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
+ bool IsMapTypeImplicit = false;
+ SourceLocation DepLinMapLoc;
+ };
+
+ /// Parses clauses with list.
+ bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind,
+ SmallVectorImpl<Expr *> &Vars,
+ OpenMPVarListDataTy &Data);
+ bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+ bool AllowDestructorName,
+ bool AllowConstructorName,
+ bool AllowDeductionGuide,
+ ParsedType ObjectType,
+ SourceLocation *TemplateKWLoc,
+ UnqualifiedId &Result);
+
+private:
+ //===--------------------------------------------------------------------===//
+ // C++ 14: Templates [temp]
+
+ // C++ 14.1: Template Parameters [temp.param]
+ Decl *ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier AS = AS_none);
+ Decl *ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier AS);
+ Decl *ParseSingleDeclarationAfterTemplate(
+ DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none);
+ bool ParseTemplateParameters(unsigned Depth,
+ SmallVectorImpl<NamedDecl *> &TemplateParams,
+ SourceLocation &LAngleLoc,
+ SourceLocation &RAngleLoc);
+ bool ParseTemplateParameterList(unsigned Depth,
+ SmallVectorImpl<NamedDecl*> &TemplateParams);
+ bool isStartOfTemplateTypeParameter();
+ NamedDecl *ParseTemplateParameter(unsigned Depth, unsigned Position);
+ NamedDecl *ParseTypeParameter(unsigned Depth, unsigned Position);
+ NamedDecl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
+ NamedDecl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
+ void DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,
+ SourceLocation CorrectLoc,
+ bool AlreadyHasEllipsis,
+ bool IdentifierHasName);
+ void DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc,
+ Declarator &D);
+ // C++ 14.3: Template arguments [temp.arg]
+ typedef SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
+
+ bool ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
+ bool ConsumeLastToken,
+ bool ObjCGenericList);
+ bool ParseTemplateIdAfterTemplateName(bool ConsumeLastToken,
+ SourceLocation &LAngleLoc,
+ TemplateArgList &TemplateArgs,
+ SourceLocation &RAngleLoc);
+
+ bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
+ CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ UnqualifiedId &TemplateName,
+ bool AllowTypeAnnotation = true);
+ void AnnotateTemplateIdTokenAsType(bool IsClassName = false);
+ bool IsTemplateArgumentList(unsigned Skip = 0);
+ bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
+ ParsedTemplateArgument ParseTemplateTemplateArgument();
+ ParsedTemplateArgument ParseTemplateArgument();
+ Decl *ParseExplicitInstantiation(DeclaratorContext Context,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &AccessAttrs,
+ AccessSpecifier AS = AS_none);
+
+ //===--------------------------------------------------------------------===//
+ // Modules
+ DeclGroupPtrTy ParseModuleDecl();
+ Decl *ParseModuleImport(SourceLocation AtLoc);
+ bool parseMisplacedModuleImport();
+ bool tryParseMisplacedModuleImport() {
+ tok::TokenKind Kind = Tok.getKind();
+ if (Kind == tok::annot_module_begin || Kind == tok::annot_module_end ||
+ Kind == tok::annot_module_include)
+ return parseMisplacedModuleImport();
+ return false;
+ }
+
+ bool ParseModuleName(
+ SourceLocation UseLoc,
+ SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> &Path,
+ bool IsImport);
+
+ //===--------------------------------------------------------------------===//
+ // C++11/G++: Type Traits [Type-Traits.html in the GCC manual]
+ ExprResult ParseTypeTrait();
+
+ //===--------------------------------------------------------------------===//
+ // Embarcadero: Arary and Expression Traits
+ ExprResult ParseArrayTypeTrait();
+ ExprResult ParseExpressionTrait();
+
+ //===--------------------------------------------------------------------===//
+ // Preprocessor code-completion pass-through
+ void CodeCompleteDirective(bool InConditional) override;
+ void CodeCompleteInConditionalExclusion() override;
+ void CodeCompleteMacroName(bool IsDefinition) override;
+ void CodeCompletePreprocessorExpression() override;
+ void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo,
+ unsigned ArgumentIndex) override;
+ void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled) override;
+ void CodeCompleteNaturalLanguage() override;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/clang-r353983/include/clang/Parse/RAIIObjectsForParser.h b/clang-r353983/include/clang/Parse/RAIIObjectsForParser.h
new file mode 100644
index 00000000..558106eb
--- /dev/null
+++ b/clang-r353983/include/clang/Parse/RAIIObjectsForParser.h
@@ -0,0 +1,465 @@
+//===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines and implements the some simple RAII objects that are used
+// by the parser to manage bits in recursion.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H
+#define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H
+
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Sema.h"
+
+namespace clang {
+ // TODO: move ParsingClassDefinition here.
+ // TODO: move TentativeParsingAction here.
+
+ /// A RAII object used to temporarily suppress access-like
+ /// checking. Access-like checks are those associated with
+ /// controlling the use of a declaration, like C++ access control
+ /// errors and deprecation warnings. They are contextually
+ /// dependent, in that they can only be resolved with full
+ /// information about what's being declared. They are also
+ /// suppressed in certain contexts, like the template arguments of
+ /// an explicit instantiation. However, those suppression contexts
+ /// cannot necessarily be fully determined in advance; for
+ /// example, something starting like this:
+ /// template <> class std::vector<A::PrivateType>
+ /// might be the entirety of an explicit instantiation:
+ /// template <> class std::vector<A::PrivateType>;
+ /// or just an elaborated type specifier:
+ /// template <> class std::vector<A::PrivateType> make_vector<>();
+ /// Therefore this class collects all the diagnostics and permits
+ /// them to be re-delayed in a new context.
+ class SuppressAccessChecks {
+ Sema &S;
+ sema::DelayedDiagnosticPool DiagnosticPool;
+ Sema::ParsingDeclState State;
+ bool Active;
+
+ public:
+ /// Begin suppressing access-like checks
+ SuppressAccessChecks(Parser &P, bool activate = true)
+ : S(P.getActions()), DiagnosticPool(nullptr) {
+ if (activate) {
+ State = S.PushParsingDeclaration(DiagnosticPool);
+ Active = true;
+ } else {
+ Active = false;
+ }
+ }
+ SuppressAccessChecks(SuppressAccessChecks &&Other)
+ : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
+ State(Other.State), Active(Other.Active) {
+ Other.Active = false;
+ }
+ void operator=(SuppressAccessChecks &&Other) = delete;
+
+ void done() {
+ assert(Active && "trying to end an inactive suppression");
+ S.PopParsingDeclaration(State, nullptr);
+ Active = false;
+ }
+
+ void redelay() {
+ assert(!Active && "redelaying without having ended first");
+ if (!DiagnosticPool.pool_empty())
+ S.redelayDiagnostics(DiagnosticPool);
+ assert(DiagnosticPool.pool_empty());
+ }
+
+ ~SuppressAccessChecks() {
+ if (Active) done();
+ }
+ };
+
+ /// 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;
+
+ ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
+ void operator=(const ParsingDeclRAIIObject &) = delete;
+
+ public:
+ enum NoParent_t { NoParent };
+ ParsingDeclRAIIObject(Parser &P, NoParent_t _)
+ : Actions(P.getActions()), DiagnosticPool(nullptr) {
+ 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() : nullptr) {
+ 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(nullptr);
+ }
+
+ void complete(Decl *D) {
+ assert(!Popped && "ParsingDeclaration has already been popped!");
+ pop(D);
+ }
+
+ /// Unregister this object from Sema, but remember all the
+ /// diagnostics that were emitted into it.
+ void abortAndRemember() {
+ pop(nullptr);
+ }
+
+ private:
+ 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, DeclaratorContext 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);
+ }
+ };
+
+ /// A class for parsing a field declarator.
+ class ParsingFieldDeclarator : public FieldDeclarator {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS)
+ : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
+ }
+
+ const ParsingDeclSpec &getDeclSpec() const {
+ return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
+ }
+
+ ParsingDeclSpec &getMutableDeclSpec() const {
+ return const_cast<ParsingDeclSpec&>(getDeclSpec());
+ }
+
+ 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
+ /// parser.
+ class ExtensionRAIIObject {
+ ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
+ void operator=(const ExtensionRAIIObject &) = delete;
+
+ DiagnosticsEngine &Diags;
+ public:
+ ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
+ Diags.IncrementAllExtensionsSilenced();
+ }
+
+ ~ExtensionRAIIObject() {
+ Diags.DecrementAllExtensionsSilenced();
+ }
+ };
+
+ /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
+ /// restores it when destroyed. This says that "foo:" should not be
+ /// considered a possible typo for "foo::" for error recovery purposes.
+ class ColonProtectionRAIIObject {
+ Parser &P;
+ bool OldVal;
+ public:
+ ColonProtectionRAIIObject(Parser &p, bool Value = true)
+ : P(p), OldVal(P.ColonIsSacred) {
+ P.ColonIsSacred = Value;
+ }
+
+ /// restore - This can be used to restore the state early, before the dtor
+ /// is run.
+ void restore() {
+ P.ColonIsSacred = OldVal;
+ }
+
+ ~ColonProtectionRAIIObject() {
+ restore();
+ }
+ };
+
+ /// RAII object that makes '>' behave either as an operator
+ /// or as the closing angle bracket for a template argument list.
+ class GreaterThanIsOperatorScope {
+ bool &GreaterThanIsOperator;
+ bool OldGreaterThanIsOperator;
+ public:
+ GreaterThanIsOperatorScope(bool &GTIO, bool Val)
+ : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
+ GreaterThanIsOperator = Val;
+ }
+
+ ~GreaterThanIsOperatorScope() {
+ GreaterThanIsOperator = OldGreaterThanIsOperator;
+ }
+ };
+
+ class InMessageExpressionRAIIObject {
+ bool &InMessageExpression;
+ bool OldValue;
+
+ public:
+ InMessageExpressionRAIIObject(Parser &P, bool Value)
+ : InMessageExpression(P.InMessageExpression),
+ OldValue(P.InMessageExpression) {
+ InMessageExpression = Value;
+ }
+
+ ~InMessageExpressionRAIIObject() {
+ InMessageExpression = OldValue;
+ }
+ };
+
+ /// RAII object that makes sure paren/bracket/brace count is correct
+ /// after declaration/statement parsing, even when there's a parsing error.
+ class ParenBraceBracketBalancer {
+ Parser &P;
+ unsigned short ParenCount, BracketCount, BraceCount;
+ public:
+ ParenBraceBracketBalancer(Parser &p)
+ : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
+ BraceCount(p.BraceCount) { }
+
+ ~ParenBraceBracketBalancer() {
+ P.AngleBrackets.clear(P);
+ P.ParenCount = ParenCount;
+ P.BracketCount = BracketCount;
+ P.BraceCount = BraceCount;
+ }
+ };
+
+ class PoisonSEHIdentifiersRAIIObject {
+ PoisonIdentifierRAIIObject Ident_AbnormalTermination;
+ PoisonIdentifierRAIIObject Ident_GetExceptionCode;
+ PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
+ PoisonIdentifierRAIIObject Ident__abnormal_termination;
+ PoisonIdentifierRAIIObject Ident__exception_code;
+ PoisonIdentifierRAIIObject Ident__exception_info;
+ PoisonIdentifierRAIIObject Ident___abnormal_termination;
+ PoisonIdentifierRAIIObject Ident___exception_code;
+ PoisonIdentifierRAIIObject Ident___exception_info;
+ public:
+ PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
+ : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
+ Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
+ Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
+ Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
+ Ident__exception_code(Self.Ident__exception_code, NewValue),
+ Ident__exception_info(Self.Ident__exception_info, NewValue),
+ Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
+ Ident___exception_code(Self.Ident___exception_code, NewValue),
+ Ident___exception_info(Self.Ident___exception_info, NewValue) {
+ }
+ };
+
+ /// RAII class that helps handle the parsing of an open/close delimiter
+ /// pair, such as braces { ... } or parentheses ( ... ).
+ class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
+ Parser& P;
+ tok::TokenKind Kind, Close, FinalToken;
+ SourceLocation (Parser::*Consumer)();
+ SourceLocation LOpen, LClose;
+
+ unsigned short &getDepth() {
+ switch (Kind) {
+ case tok::l_brace: return P.BraceCount;
+ case tok::l_square: return P.BracketCount;
+ case tok::l_paren: return P.ParenCount;
+ default: llvm_unreachable("Wrong token kind");
+ }
+ }
+
+ bool diagnoseOverflow();
+ bool diagnoseMissingClose();
+
+ public:
+ BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
+ tok::TokenKind FinalToken = tok::semi)
+ : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
+ P(p), Kind(k), FinalToken(FinalToken)
+ {
+ switch (Kind) {
+ default: llvm_unreachable("Unexpected balanced token");
+ case tok::l_brace:
+ Close = tok::r_brace;
+ Consumer = &Parser::ConsumeBrace;
+ break;
+ case tok::l_paren:
+ Close = tok::r_paren;
+ Consumer = &Parser::ConsumeParen;
+ break;
+
+ case tok::l_square:
+ Close = tok::r_square;
+ Consumer = &Parser::ConsumeBracket;
+ break;
+ }
+ }
+
+ SourceLocation getOpenLocation() const { return LOpen; }
+ SourceLocation getCloseLocation() const { return LClose; }
+ SourceRange getRange() const { return SourceRange(LOpen, LClose); }
+
+ bool consumeOpen() {
+ if (!P.Tok.is(Kind))
+ return true;
+
+ if (getDepth() < P.getLangOpts().BracketDepth) {
+ LOpen = (P.*Consumer)();
+ return false;
+ }
+
+ return diagnoseOverflow();
+ }
+
+ bool expectAndConsume(unsigned DiagID = diag::err_expected,
+ const char *Msg = "",
+ tok::TokenKind SkipToTok = tok::unknown);
+ bool consumeClose() {
+ if (P.Tok.is(Close)) {
+ LClose = (P.*Consumer)();
+ return false;
+ } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
+ SourceLocation SemiLoc = P.ConsumeToken();
+ P.Diag(SemiLoc, diag::err_unexpected_semi)
+ << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
+ LClose = (P.*Consumer)();
+ return false;
+ }
+
+ return diagnoseMissingClose();
+ }
+ void skipToEnd();
+ };
+
+ /// RAIIObject to destroy the contents of a SmallVector of
+ /// TemplateIdAnnotation pointers and clear the vector.
+ class DestroyTemplateIdAnnotationsRAIIObj {
+ SmallVectorImpl<TemplateIdAnnotation *> &Container;
+
+ public:
+ DestroyTemplateIdAnnotationsRAIIObj(
+ SmallVectorImpl<TemplateIdAnnotation *> &Container)
+ : Container(Container) {}
+
+ ~DestroyTemplateIdAnnotationsRAIIObj() {
+ for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
+ Container.begin(),
+ E = Container.end();
+ I != E; ++I)
+ (*I)->Destroy();
+ Container.clear();
+ }
+ };
+} // end namespace clang
+
+#endif