llvm/clang/lib/Parse/ParseTentative.cpp

//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
//
// 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 implements the tentative parsing portions of the Parser
//  interfaces, for ambiguity resolution.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/ParsedTemplate.h"
usingnamespaceclang;

/// isCXXDeclarationStatement - C++-specialized function that disambiguates
/// between a declaration or an expression statement, when parsing function
/// bodies. Returns true for declaration, false for expression.
///
///         declaration-statement:
///           block-declaration
///
///         block-declaration:
///           simple-declaration
///           asm-definition
///           namespace-alias-definition
///           using-declaration
///           using-directive
/// [C++0x]   static_assert-declaration
///
///         asm-definition:
///           'asm' '(' string-literal ')' ';'
///
///         namespace-alias-definition:
///           'namespace' identifier = qualified-namespace-specifier ';'
///
///         using-declaration:
///           'using' typename[opt] '::'[opt] nested-name-specifier
///                 unqualified-id ';'
///           'using' '::' unqualified-id ;
///
///         using-directive:
///           'using' 'namespace' '::'[opt] nested-name-specifier[opt]
///                 namespace-name ';'
///
bool Parser::isCXXDeclarationStatement(
    bool DisambiguatingWithExpression /*=false*/) {}

/// 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.
///
/// simple-declaration:
///   decl-specifier-seq init-declarator-list[opt] ';'
///   decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
///                      brace-or-equal-initializer ';'    [C++17]
///
/// (if AllowForRangeDecl specified)
/// for ( for-range-declaration : for-range-initializer ) statement
///
/// for-range-declaration:
///    decl-specifier-seq declarator
///    decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
///
/// In any of the above cases there can be a preceding attribute-specifier-seq,
/// but the caller is expected to handle that.
bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {}

/// Try to consume a token sequence that we've already identified as
/// (potentially) starting a decl-specifier.
Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {}

/// simple-declaration:
///   decl-specifier-seq init-declarator-list[opt] ';'
///
/// (if AllowForRangeDecl specified)
/// for ( for-range-declaration : for-range-initializer ) statement
/// for-range-declaration:
///    attribute-specifier-seqopt type-specifier-seq declarator
///
Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {}

/// Tentatively parse an init-declarator-list in order to disambiguate it from
/// an expression.
///
///       init-declarator-list:
///         init-declarator
///         init-declarator-list ',' init-declarator
///
///       init-declarator:
///         declarator initializer[opt]
/// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
///
///       initializer:
///         brace-or-equal-initializer
///         '(' expression-list ')'
///
///       brace-or-equal-initializer:
///         '=' initializer-clause
/// [C++11] braced-init-list
///
///       initializer-clause:
///         assignment-expression
///         braced-init-list
///
///       braced-init-list:
///         '{' initializer-list ','[opt] '}'
///         '{' '}'
///
Parser::TPResult
Parser::TryParseInitDeclaratorList(bool MayHaveTrailingReturnType) {}

struct Parser::ConditionDeclarationOrInitStatementState {};

bool Parser::isEnumBase(bool AllowSemi) {}

/// Disambiguates between a declaration in a condition, a
/// simple-declaration in an init-statement, and an expression for
/// a condition of a if/switch statement.
///
///       condition:
///         expression
///         type-specifier-seq declarator '=' assignment-expression
/// [C++11] type-specifier-seq declarator '=' initializer-clause
/// [C++11] type-specifier-seq declarator braced-init-list
/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
///             '=' assignment-expression
///       simple-declaration:
///         decl-specifier-seq init-declarator-list[opt] ';'
///
/// Note that, unlike isCXXSimpleDeclaration, we must disambiguate all the way
/// to the ';' to disambiguate cases like 'int(x))' (an expression) from
/// 'int(x);' (a simple-declaration in an init-statement).
Parser::ConditionOrInitStatement
Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,
                                                 bool CanBeForRangeDecl) {}

  /// Determine whether the next set of tokens contains a type-id.
  ///
  /// The context parameter states what context we're parsing right
  /// now, which affects how this routine copes with the token
  /// following the type-id. If the context is TypeIdInParens, we have
  /// already parsed the '(' and we will cease lookahead when we hit
  /// the corresponding ')'. If the context is
  /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
  /// before this template argument, and will cease lookahead when we
  /// hit a '>', '>>' (in C++0x), or ','; or, in C++0x, an ellipsis immediately
  /// preceding such. Returns true for a type-id and false for an expression.
  /// If during the disambiguation process a parsing error is encountered,
  /// the function returns true to let the declaration parsing code handle it.
  ///
  /// type-id:
  ///   type-specifier-seq abstract-declarator[opt]
  ///
bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {}

/// Returns true if this is a C++11 attribute-specifier. Per
/// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens
/// always introduce an attribute. In Objective-C++11, this rule does not
/// apply if either '[' begins a message-send.
///
/// If Disambiguate is true, we try harder to determine whether a '[[' starts
/// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not.
///
/// If OuterMightBeMessageSend is true, we assume the outer '[' is either an
/// Obj-C message send or the start of an attribute. Otherwise, we assume it
/// is not an Obj-C message send.
///
/// C++11 [dcl.attr.grammar]:
///
///     attribute-specifier:
///         '[' '[' attribute-list ']' ']'
///         alignment-specifier
///
///     attribute-list:
///         attribute[opt]
///         attribute-list ',' attribute[opt]
///         attribute '...'
///         attribute-list ',' attribute '...'
///
///     attribute:
///         attribute-token attribute-argument-clause[opt]
///
///     attribute-token:
///         identifier
///         identifier '::' identifier
///
///     attribute-argument-clause:
///         '(' balanced-token-seq ')'
Parser::CXX11AttributeKind
Parser::isCXX11AttributeSpecifier(bool Disambiguate,
                                  bool OuterMightBeMessageSend) {}

bool Parser::TrySkipAttributes() {}

Parser::TPResult Parser::TryParsePtrOperatorSeq() {}

///         operator-function-id:
///           'operator' operator
///
///         operator: one of
///           new  delete  new[]  delete[]  +  -  *  /  %  ^  [...]
///
///         conversion-function-id:
///           'operator' conversion-type-id
///
///         conversion-type-id:
///           type-specifier-seq conversion-declarator[opt]
///
///         conversion-declarator:
///           ptr-operator conversion-declarator[opt]
///
///         literal-operator-id:
///           'operator' string-literal identifier
///           'operator' user-defined-string-literal
Parser::TPResult Parser::TryParseOperatorId() {}

///         declarator:
///           direct-declarator
///           ptr-operator declarator
///
///         direct-declarator:
///           declarator-id
///           direct-declarator '(' parameter-declaration-clause ')'
///                 cv-qualifier-seq[opt] exception-specification[opt]
///           direct-declarator '[' constant-expression[opt] ']'
///           '(' declarator ')'
/// [GNU]     '(' attributes declarator ')'
///
///         abstract-declarator:
///           ptr-operator abstract-declarator[opt]
///           direct-abstract-declarator
///
///         direct-abstract-declarator:
///           direct-abstract-declarator[opt]
///                 '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
///                 exception-specification[opt]
///           direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
///           '(' abstract-declarator ')'
/// [C++0x]   ...
///
///         ptr-operator:
///           '*' cv-qualifier-seq[opt]
///           '&'
/// [C++0x]   '&&'                                                        [TODO]
///           '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
///
///         cv-qualifier-seq:
///           cv-qualifier cv-qualifier-seq[opt]
///
///         cv-qualifier:
///           'const'
///           'volatile'
///
///         declarator-id:
///           '...'[opt] id-expression
///
///         id-expression:
///           unqualified-id
///           qualified-id                                                [TODO]
///
///         unqualified-id:
///           identifier
///           operator-function-id
///           conversion-function-id
///           literal-operator-id
///           '~' class-name                                              [TODO]
///           '~' decltype-specifier                                      [TODO]
///           template-id                                                 [TODO]
///
Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
                                            bool mayHaveIdentifier,
                                            bool mayHaveDirectInit,
                                            bool mayHaveTrailingReturnType) {}

bool Parser::isTentativelyDeclared(IdentifierInfo *II) {}

namespace {
class TentativeParseCCC final : public CorrectionCandidateCallback {};
}
/// 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 found and reported.
///
/// If InvalidAsDeclSpec is not null, some cases that would be ill-formed as
/// declaration specifiers but possibly valid as some other kind of construct
/// return TPResult::Ambiguous instead of TPResult::False. When this happens,
/// the intent is to keep trying to disambiguate, on the basis that we might
/// find a better reason to treat this construct as a declaration later on.
/// When this happens and the name could possibly be valid in some other
/// syntactic context, *InvalidAsDeclSpec is set to 'true'. The current cases
/// that trigger this are:
///
///   * When parsing X::Y (with no 'typename') where X is dependent
///   * When parsing X<Y> where X is undeclared
///
///         decl-specifier:
///           storage-class-specifier
///           type-specifier
///           function-specifier
///           'friend'
///           'typedef'
/// [C++11]   'constexpr'
/// [C++20]   'consteval'
/// [GNU]     attributes declaration-specifiers[opt]
///
///         storage-class-specifier:
///           'register'
///           'static'
///           'extern'
///           'mutable'
///           'auto'
/// [GNU]     '__thread'
/// [C++11]   'thread_local'
/// [C11]     '_Thread_local'
///
///         function-specifier:
///           'inline'
///           'virtual'
///           'explicit'
///
///         typedef-name:
///           identifier
///
///         type-specifier:
///           simple-type-specifier
///           class-specifier
///           enum-specifier
///           elaborated-type-specifier
///           typename-specifier
///           cv-qualifier
///
///         simple-type-specifier:
///           '::'[opt] nested-name-specifier[opt] type-name
///           '::'[opt] nested-name-specifier 'template'
///                 simple-template-id                              [TODO]
///           'char'
///           'wchar_t'
///           'bool'
///           'short'
///           'int'
///           'long'
///           'signed'
///           'unsigned'
///           'float'
///           'double'
///           'void'
/// [GNU]     typeof-specifier
/// [GNU]     '_Complex'
/// [C++11]   'auto'
/// [GNU]     '__auto_type'
/// [C++11]   'decltype' ( expression )
/// [C++1y]   'decltype' ( 'auto' )
///
///         type-name:
///           class-name
///           enum-name
///           typedef-name
///
///         elaborated-type-specifier:
///           class-key '::'[opt] nested-name-specifier[opt] identifier
///           class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
///               simple-template-id
///           'enum' '::'[opt] nested-name-specifier[opt] identifier
///
///         enum-name:
///           identifier
///
///         enum-specifier:
///           'enum' identifier[opt] '{' enumerator-list[opt] '}'
///           'enum' identifier[opt] '{' enumerator-list ',' '}'
///
///         class-specifier:
///           class-head '{' member-specification[opt] '}'
///
///         class-head:
///           class-key identifier[opt] base-clause[opt]
///           class-key nested-name-specifier identifier base-clause[opt]
///           class-key nested-name-specifier[opt] simple-template-id
///               base-clause[opt]
///
///         class-key:
///           'class'
///           'struct'
///           'union'
///
///         cv-qualifier:
///           'const'
///           'volatile'
/// [GNU]     restrict
///
Parser::TPResult
Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
                                  Parser::TPResult BracedCastResult,
                                  bool *InvalidAsDeclSpec) {}

bool Parser::isCXXDeclarationSpecifierAType() {}

/// [GNU] typeof-specifier:
///         'typeof' '(' expressions ')'
///         'typeof' '(' type-name ')'
///
Parser::TPResult Parser::TryParseTypeofSpecifier() {}

/// [ObjC] protocol-qualifiers:
////         '<' identifier-list '>'
Parser::TPResult Parser::TryParseProtocolQualifiers() {}

/// 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.
/// If during the disambiguation process a parsing error is encountered,
/// the function returns true to let the declaration parsing code handle it.
///
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
///         exception-specification[opt]
///
bool Parser::isCXXFunctionDeclarator(
    bool *IsAmbiguous, ImplicitTypenameContext AllowImplicitTypename) {}

/// parameter-declaration-clause:
///   parameter-declaration-list[opt] '...'[opt]
///   parameter-declaration-list ',' '...'
///
/// parameter-declaration-list:
///   parameter-declaration
///   parameter-declaration-list ',' parameter-declaration
///
/// parameter-declaration:
///   attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
///   attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
///     '=' assignment-expression
///   attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
///     attributes[opt]
///   attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
///     attributes[opt] '=' assignment-expression
///
Parser::TPResult Parser::TryParseParameterDeclarationClause(
    bool *InvalidAsDeclaration, bool VersusTemplateArgument,
    ImplicitTypenameContext AllowImplicitTypename) {}

/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
/// parsing as a function declarator.
/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
/// return TPResult::Ambiguous, otherwise it will return either False() or
/// Error().
///
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
///         exception-specification[opt]
///
/// exception-specification:
///   'throw' '(' type-id-list[opt] ')'
///
Parser::TPResult
Parser::TryParseFunctionDeclarator(bool MayHaveTrailingReturnType) {}

// When parsing an identifier after an arrow it may be a member expression,
// in which case we should not annotate it as an independant expression
// so we just lookup that name, if it's not a type the construct is not
// a function declaration.
bool Parser::NameAfterArrowIsNonType() {}

/// '[' constant-expression[opt] ']'
///
Parser::TPResult Parser::TryParseBracketDeclarator() {}

/// Determine whether we might be looking at the '<' template-argument-list '>'
/// of a template-id or simple-template-id, rather than a less-than comparison.
/// This will often fail and produce an ambiguity, but should never be wrong
/// if it returns True or False.
Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip) {}

/// Determine whether we might be looking at the '(' of a C++20 explicit(bool)
/// in an earlier language mode.
Parser::TPResult Parser::isExplicitBool() {}