//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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"
using namespace clang;
/// 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() {
switch (Tok.getKind()) {
// asm-definition
case tok::kw_asm:
// namespace-alias-definition
case tok::kw_namespace:
// using-declaration
// using-directive
case tok::kw_using:
// static_assert-declaration
case tok::kw_static_assert:
case tok::kw__Static_assert:
return true;
// simple-declaration
default:
return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/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] ';'
///
/// (if AllowForRangeDecl specified)
/// for ( for-range-declaration : for-range-initializer ) statement
/// for-range-declaration:
/// attribute-specifier-seqopt type-specifier-seq declarator
bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
// C++ 6.8p1:
// There is an ambiguity in the grammar involving expression-statements and
// declarations: An expression-statement with a function-style explicit type
// conversion (5.2.3) as its leftmost subexpression can be indistinguishable
// from a declaration where the first declarator starts with a '('. In those
// cases the statement is a declaration. [Note: To disambiguate, the whole
// statement might have to be examined to determine if it is an
// expression-statement or a declaration].
// C++ 6.8p3:
// The disambiguation is purely syntactic; that is, the meaning of the names
// occurring in such a statement, beyond whether they are type-names or not,
// is not generally used in or changed by the disambiguation. Class
// templates are instantiated as necessary to determine if a qualified name
// is a type-name. Disambiguation precedes parsing, and a statement
// disambiguated as a declaration may be an ill-formed declaration.
// We don't have to parse all of the decl-specifier-seq part. There's only
// an ambiguity if the first decl-specifier is
// simple-type-specifier/typename-specifier followed by a '(', which may
// indicate a function-style cast expression.
// isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
// a case.
TPResult TPR = isCXXDeclarationSpecifier();
if (TPR != TPResult::Ambiguous())
return TPR != TPResult::False();