summaryrefslogtreecommitdiffstats
path: root/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/Parser.cpp')
-rw-r--r--lib/Parse/Parser.cpp208
1 files changed, 156 insertions, 52 deletions
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 44bd0fb..a50763a 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -23,8 +23,8 @@ using namespace clang;
Parser::Parser(Preprocessor &pp, Sema &actions)
: CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
- GreaterThanIsOperator(true), ColonIsSacred(false),
- TemplateParameterDepth(0) {
+ GreaterThanIsOperator(true), ColonIsSacred(false),
+ InMessageExpression(false), TemplateParameterDepth(0) {
Tok.setKind(tok::eof);
Actions.CurScope = 0;
NumCachedScopes = 0;
@@ -50,6 +50,17 @@ Parser::Parser(Preprocessor &pp, Sema &actions)
WeakHandler.reset(new PragmaWeakHandler(actions));
PP.AddPragmaHandler(WeakHandler.get());
+
+ FPContractHandler.reset(new PragmaFPContractHandler(actions, *this));
+ PP.AddPragmaHandler("STDC", FPContractHandler.get());
+
+ if (getLang().OpenCL) {
+ OpenCLExtensionHandler.reset(
+ new PragmaOpenCLExtensionHandler(actions, *this));
+ PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+
+ PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
+ }
PP.setCodeCompletionHandler(*this);
}
@@ -78,7 +89,7 @@ void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const {
DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) {
- return Diags.Report(FullSourceLoc(Loc, PP.getSourceManager()), DiagID);
+ return Diags.Report(Loc, DiagID);
}
DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) {
@@ -126,6 +137,8 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break;
+ case tok::greatergreatergreater:
+ LHSName = "<<<"; DID = diag::err_expected_ggg; break;
}
Diag(Tok, DID);
Diag(LHSLoc, diag::note_matching) << LHSName;
@@ -133,6 +146,13 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
return R;
}
+static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) {
+ switch (ExpectedTok) {
+ case tok::semi: return Tok.is(tok::colon); // : for ;
+ default: return false;
+ }
+}
+
/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
/// input. If so, it is consumed and false is returned.
///
@@ -146,6 +166,19 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
return false;
}
+ // Detect common single-character typos and resume.
+ if (IsCommonTypo(ExpectedTok, Tok)) {
+ SourceLocation Loc = Tok.getLocation();
+ Diag(Loc, DiagID)
+ << Msg
+ << FixItHint::CreateReplacement(SourceRange(Loc),
+ getTokenSimpleSpelling(ExpectedTok));
+ ConsumeAnyToken();
+
+ // Pretend there wasn't a problem.
+ return false;
+ }
+
const char *Spelling = 0;
SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
if (EndLoc.isValid() &&
@@ -162,6 +195,25 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
return true;
}
+bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
+ if (Tok.is(tok::semi) || Tok.is(tok::code_completion)) {
+ ConsumeAnyToken();
+ return false;
+ }
+
+ if ((Tok.is(tok::r_paren) || Tok.is(tok::r_square)) &&
+ NextToken().is(tok::semi)) {
+ Diag(Tok, diag::err_extraneous_token_before_semi)
+ << PP.getSpelling(Tok)
+ << FixItHint::CreateRemoval(Tok.getLocation());
+ ConsumeAnyToken(); // The ')' or ']'.
+ ConsumeToken(); // The ';'.
+ return false;
+ }
+
+ return ExpectAndConsume(tok::semi, DiagID);
+}
+
//===----------------------------------------------------------------------===//
// Error recovery.
//===----------------------------------------------------------------------===//
@@ -175,7 +227,8 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
/// If SkipUntil finds the specified token, it returns true, otherwise it
/// returns false.
bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
- bool StopAtSemi, bool DontConsume) {
+ bool StopAtSemi, bool DontConsume,
+ bool StopAtCodeCompletion) {
// We always want this function to skip at least one token if the first token
// isn't T and if not at EOF.
bool isFirstTokenSkipped = true;
@@ -198,23 +251,24 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
return false;
case tok::code_completion:
- ConsumeToken();
+ if (!StopAtCodeCompletion)
+ ConsumeToken();
return false;
case tok::l_paren:
// Recursively skip properly-nested parens.
ConsumeParen();
- SkipUntil(tok::r_paren, false);
+ SkipUntil(tok::r_paren, false, false, StopAtCodeCompletion);
break;
case tok::l_square:
// Recursively skip properly-nested square brackets.
ConsumeBracket();
- SkipUntil(tok::r_square, false);
+ SkipUntil(tok::r_square, false, false, StopAtCodeCompletion);
break;
case tok::l_brace:
// Recursively skip properly-nested braces.
ConsumeBrace();
- SkipUntil(tok::r_brace, false);
+ SkipUntil(tok::r_brace, false, false, StopAtCodeCompletion);
break;
// Okay, we found a ']' or '}' or ')', which we think should be balanced.
@@ -266,9 +320,8 @@ void Parser::EnterScope(unsigned ScopeFlags) {
N->Init(getCurScope(), ScopeFlags);
Actions.CurScope = N;
} else {
- Actions.CurScope = new Scope(getCurScope(), ScopeFlags);
+ Actions.CurScope = new Scope(getCurScope(), ScopeFlags, Diags);
}
- getCurScope()->setNumErrorsAtStart(Diags.getNumErrors());
}
/// ExitScope - Pop a scope off the scope stack.
@@ -318,6 +371,15 @@ Parser::~Parser() {
UnusedHandler.reset();
PP.RemovePragmaHandler(WeakHandler.get());
WeakHandler.reset();
+
+ if (getLang().OpenCL) {
+ PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+ OpenCLExtensionHandler.reset();
+ PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
+ }
+
+ PP.RemovePragmaHandler("STDC", FPContractHandler.get());
+ FPContractHandler.reset();
PP.clearCodeCompletionHandler();
}
@@ -347,6 +409,9 @@ void Parser::Initialize() {
ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
}
+ Ident_final = 0;
+ Ident_override = 0;
+
Ident_super = &PP.getIdentifierTable().get("super");
if (getLang().AltiVec) {
@@ -358,16 +423,21 @@ void Parser::Initialize() {
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
/// action tells us to. This returns true if the EOF was encountered.
bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
+
+ while (Tok.is(tok::annot_pragma_unused))
+ HandlePragmaUnused();
+
Result = DeclGroupPtrTy();
if (Tok.is(tok::eof)) {
Actions.ActOnEndOfTranslationUnit();
return true;
}
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
- Attr = ParseCXX0XAttributes();
- Result = ParseExternalDeclaration(Attr);
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+
+ Result = ParseExternalDeclaration(attrs);
return false;
}
@@ -408,8 +478,9 @@ void Parser::ParseTranslationUnit() {
/// ';'
///
/// [C++0x/GNU] 'extern' 'template' declaration
-Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
- ParsingDeclSpec *DS) {
+Parser::DeclGroupPtrTy
+Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
Decl *SingleDecl = 0;
@@ -433,12 +504,10 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
ConsumeToken();
- return ParseExternalDeclaration(Attr);
+ return ParseExternalDeclaration(attrs);
}
case tok::kw_asm: {
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
ExprResult Result(ParseSimpleAsm());
@@ -470,7 +539,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
ObjCImpDecl? Sema::PCC_ObjCImplementation
: Sema::PCC_Namespace);
ConsumeCodeCompletionToken();
- return ParseExternalDeclaration(Attr);
+ return ParseExternalDeclaration(attrs);
case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
@@ -480,14 +549,42 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
// A function definition cannot start with a these keywords.
{
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
+ StmtVector Stmts(Actions);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
}
+ case tok::kw_static:
+ // Parse (then ignore) 'static' prior to a template instantiation. This is
+ // a GCC extension that we intentionally do not support.
+ if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
+ Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
+ << 0;
+ SourceLocation DeclEnd;
+ StmtVector Stmts(Actions);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
+ }
+ goto dont_know;
+
case tok::kw_inline:
- if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) {
+ if (getLang().CPlusPlus) {
+ tok::TokenKind NextKind = NextToken().getKind();
+
// Inline namespaces. Allowed as an extension even in C++03.
- SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
+ if (NextKind == tok::kw_namespace) {
+ SourceLocation DeclEnd;
+ StmtVector Stmts(Actions);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
+ }
+
+ // Parse (then ignore) 'inline' prior to a template instantiation. This is
+ // a GCC extension that we intentionally do not support.
+ if (NextKind == tok::kw_template) {
+ Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
+ << 1;
+ SourceLocation DeclEnd;
+ StmtVector Stmts(Actions);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
+ }
}
goto dont_know;
@@ -506,10 +603,12 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
default:
dont_know:
// We can't tell whether this is a function-definition or declaration yet.
- if (DS)
- return ParseDeclarationOrFunctionDefinition(*DS, Attr.AttrList);
- else
- return ParseDeclarationOrFunctionDefinition(Attr.AttrList);
+ if (DS) {
+ DS->takeAttributesFrom(attrs);
+ return ParseDeclarationOrFunctionDefinition(*DS);
+ } else {
+ return ParseDeclarationOrFunctionDefinition(attrs);
+ }
}
// This routine returns a DeclGroup, if the thing we parsed only contains a
@@ -532,14 +631,13 @@ bool Parser::isDeclarationAfterDeclarator() const {
/// \brief Determine whether the current token, if it occurs after a
/// declarator, indicates the start of a function definition.
bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
- assert(Declarator.getTypeObject(0).Kind == DeclaratorChunk::Function &&
- "Isn't a function declarator");
+ assert(Declarator.isFunctionDeclarator() && "Isn't a function declarator");
if (Tok.is(tok::l_brace)) // int X() {}
return true;
// Handle K&R C argument lists: int X(f) int f; {}
if (!getLang().CPlusPlus &&
- Declarator.getTypeObject(0).Fun.isKNRPrototype())
+ Declarator.getFunctionTypeInfo().isKNRPrototype())
return isDeclarationSpecifier();
return Tok.is(tok::colon) || // X() : Base() {} (used for ctors)
@@ -564,12 +662,8 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
///
Parser::DeclGroupPtrTy
Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
- AttributeList *Attr,
AccessSpecifier AS) {
// Parse the common declaration-specifiers piece.
- if (Attr)
- DS.AddAttributes(Attr);
-
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -622,10 +716,11 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
}
Parser::DeclGroupPtrTy
-Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
+Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
AccessSpecifier AS) {
ParsingDeclSpec DS(*this);
- return ParseDeclarationOrFunctionDefinition(DS, Attr, AS);
+ DS.takeAttributesFrom(attrs);
+ return ParseDeclarationOrFunctionDefinition(DS, AS);
}
/// ParseFunctionDefinition - We parsed and verified that the specified
@@ -643,11 +738,8 @@ Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
/// decl-specifier-seq[opt] declarator function-try-block
///
Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
- const ParsedTemplateInfo &TemplateInfo) {
- const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
- assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
- "This isn't a function declarator!");
- const DeclaratorChunk::FunctionTypeInfo &FTI = FnTypeInfo.Fun;
+ const ParsedTemplateInfo &TemplateInfo) {
+ const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
// If this is C90 and the declspecs were completely missing, fudge in an
// implicit int. We do this here because this is the only place where
@@ -669,8 +761,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// We should have either an opening brace or, in a C++ constructor,
// we may have a colon.
- if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon) &&
- Tok.isNot(tok::kw_try)) {
+ if (Tok.isNot(tok::l_brace) &&
+ (!getLang().CPlusPlus ||
+ (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try)))) {
Diag(Tok, diag::err_expected_fn_body);
// Skip over garbage, until we get to '{'. Don't eat the '{'.
@@ -724,7 +817,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
/// types for a function with a K&R-style identifier list for arguments.
void Parser::ParseKNRParamDeclarations(Declarator &D) {
// We know that the top-level of this declarator is a function.
- DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
// Enter function-declaration scope, limiting any declarators to the
// function prototype scope, including parameter declarators.
@@ -770,11 +863,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
// Handle the full declarator list.
while (1) {
// If attributes are present, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- ParmDeclarator.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(ParmDeclarator);
// Ask the actions module to compute the type for this declarator.
Decl *Param =
@@ -994,7 +1083,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// Determine whether the identifier is a type name.
if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), getCurScope(),
- &SS)) {
+ &SS, false,
+ NextToken().is(tok::period))) {
// This is a typename. Replace the current token in-place with an
// annotation type token.
Tok.setKind(tok::annot_typename);
@@ -1115,6 +1205,20 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
return false;
}
+bool Parser::isTokenEqualOrMistypedEqualEqual(unsigned DiagID) {
+ if (Tok.is(tok::equalequal)) {
+ // We have '==' in a context that we would expect a '='.
+ // The user probably made a typo, intending to type '='. Emit diagnostic,
+ // fixit hint to turn '==' -> '=' and continue as if the user typed '='.
+ Diag(Tok, DiagID)
+ << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()),
+ getTokenSimpleSpelling(tok::equal));
+ return true;
+ }
+
+ return Tok.is(tok::equal);
+}
+
void Parser::CodeCompletionRecovery() {
for (Scope *S = getCurScope(); S; S = S->getParent()) {
if (S->getFlags() & Scope::FnScope) {
OpenPOWER on IntegriCloud