diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Parse/ParseAST.cpp | 61 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 55 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 450 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 373 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 139 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 74 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 125 | ||||
-rw-r--r-- | lib/Parse/ParseOpenMP.cpp | 118 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 46 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.h | 15 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 114 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 197 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 53 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 105 | ||||
-rw-r--r-- | lib/Parse/RAIIObjectsForParser.h | 2 |
17 files changed, 1261 insertions, 671 deletions
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt index 55e2aeb..939998e 100644 --- a/lib/Parse/CMakeLists.txt +++ b/lib/Parse/CMakeLists.txt @@ -7,6 +7,7 @@ add_clang_library(clangParse ParseExprCXX.cpp ParseInit.cpp ParseObjc.cpp + ParseOpenMP.cpp ParsePragma.cpp ParseStmt.cpp ParseTemplate.cpp diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp index 7d68e1f..7cd8a21 100644 --- a/lib/Parse/ParseAST.cpp +++ b/lib/Parse/ParseAST.cpp @@ -12,23 +12,68 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/ParseAST.h" -#include "clang/Parse/ParseDiagnostic.h" -#include "clang/Sema/Sema.h" -#include "clang/Sema/CodeCompleteConsumer.h" -#include "clang/Sema/SemaConsumer.h" -#include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Stmt.h" +#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaConsumer.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CrashRecoveryContext.h" #include <cstdio> using namespace clang; +namespace { + +/// If a crash happens while the parser is active, an entry is printed for it. +class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { + const Parser &P; +public: + PrettyStackTraceParserEntry(const Parser &p) : P(p) {} + virtual void print(raw_ostream &OS) const; +}; + +/// If a crash happens while the parser is active, print out a line indicating +/// what the current token is. +void PrettyStackTraceParserEntry::print(raw_ostream &OS) const { + const Token &Tok = P.getCurToken(); + if (Tok.is(tok::eof)) { + OS << "<eof> parser at end of file\n"; + return; + } + + if (Tok.getLocation().isInvalid()) { + OS << "<unknown> parser at unknown location\n"; + return; + } + + const Preprocessor &PP = P.getPreprocessor(); + Tok.getLocation().print(OS, PP.getSourceManager()); + if (Tok.isAnnotation()) { + OS << ": at annotation token\n"; + } else { + // Do the equivalent of PP.getSpelling(Tok) except for the parts that would + // allocate memory. + bool Invalid = false; + const SourceManager &SM = P.getPreprocessor().getSourceManager(); + unsigned Length = Tok.getLength(); + const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid); + if (Invalid) { + OS << ": unknown current parser token\n"; + return; + } + OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n"; + } +} + +} // namespace + //===----------------------------------------------------------------------===// // Public interface to the file //===----------------------------------------------------------------------===// @@ -43,9 +88,7 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, CodeCompleteConsumer *CompletionConsumer, bool SkipFunctionBodies) { - OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer, - TUKind, - CompletionConsumer)); + OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get()); @@ -97,7 +140,7 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { // is due to a top-level semicolon, an action override, or a parse error // skipping something. if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) - return; + return; } while (!P.ParseTopLevelDecl(ADecl)); } diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 9c5c0597..bc634b5 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -11,18 +11,25 @@ // //===----------------------------------------------------------------------===// -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "RAIIObjectsForParser.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" -#include "clang/AST/DeclTemplate.h" -#include "RAIIObjectsForParser.h" using namespace clang; +/// Get the FunctionDecl for a function or function template decl. +static FunctionDecl *getFunctionDecl(Decl *D) { + if (FunctionDecl *fn = dyn_cast<FunctionDecl>(D)) + return fn; + return cast<FunctionTemplateDecl>(D)->getTemplatedDecl(); +} + /// ParseCXXInlineMethodDef - We parsed and verified that the specified /// Declarator is a well formed C++ inline method definition. Now lex its body /// and store its tokens for parsing after the C++ class is complete. -Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, +NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, AttributeList *AccessAttrs, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, @@ -38,7 +45,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); - Decl *FnD; + NamedDecl *FnD; D.setFunctionDefinitionKind(DefinitionKind); if (D.getDeclSpec().isFriendSpecified()) FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, @@ -75,7 +82,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, bool Delete = false; SourceLocation KWLoc; if (Tok.is(tok::kw_delete)) { - Diag(Tok, getLangOpts().CPlusPlus0x ? + Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_deleted_function : diag::ext_deleted_function); @@ -83,7 +90,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Actions.SetDeclDeleted(FnD, KWLoc); Delete = true; } else if (Tok.is(tok::kw_default)) { - Diag(Tok, getLangOpts().CPlusPlus0x ? + Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_defaulted_function : diag::ext_defaulted_function); @@ -117,11 +124,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, if (FnD) { LateParsedTemplatedFunction *LPT = new LateParsedTemplatedFunction(FnD); - FunctionDecl *FD = 0; - if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(FnD)) - FD = FunTmpl->getTemplatedDecl(); - else - FD = cast<FunctionDecl>(FnD); + FunctionDecl *FD = getFunctionDecl(FnD); Actions.CheckForFunctionRedefinition(FD); LateParsedTemplateMap[FD] = LPT; @@ -176,6 +179,19 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, getCurrentClass().LateParsedDeclarations.pop_back(); } + // If this is a friend function, mark that it's late-parsed so that + // it's still known to be a definition even before we attach the + // parsed body. Sema needs to treat friend function definitions + // differently during template instantiation, and it's possible for + // the containing class to be instantiated before all its member + // function definitions are parsed. + // + // If you remove this, you can remove the code that clears the flag + // after parsing the member. + if (D.getDeclSpec().isFriendSpecified()) { + getFunctionDecl(FnD)->setLateTemplateParsed(true); + } + return FnD; } @@ -293,8 +309,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // Introduce the parameters into scope and parse their default // arguments. - ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); + ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | Scope::DeclScope); for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { // Introduce the parameter into scope. Actions.ActOnDelayedCXXMethodParameter(getCurScope(), @@ -322,7 +338,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { LM.DefaultArgs[I].Param); ExprResult DefArgResult; - if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); DefArgResult = ParseBraceInitializer(); } else @@ -391,7 +407,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); // Consume the previously pushed token. - ConsumeAnyToken(); + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && "Inline method not starting with '{', ':' or 'try'"); @@ -427,6 +443,9 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { ParseFunctionStatementBody(LM.D, FnScope); + // Clear the late-template-parsed bit if we set it before. + if (LM.D) getFunctionDecl(LM.D)->setLateTemplateParsed(false); + if (Tok.getLocation() != origLoc) { // Due to parsing error, we either went over the cached tokens or // there are still cached tokens left. If it's the latter case skip the @@ -491,7 +510,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false); // Consume the previously pushed token. - ConsumeAnyToken(); + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); SourceLocation EqualLoc; @@ -651,7 +670,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { ConsumeBrace(); // In C++03, this has to be the start of the function body, which // means the initializer is malformed; we'll diagnose it later. - if (!getLangOpts().CPlusPlus0x) + if (!getLangOpts().CPlusPlus11) return false; } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index f73907a..990a909 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -12,13 +12,15 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "clang/Parse/ParseDiagnostic.h" +#include "RAIIObjectsForParser.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/OpenCL.h" +#include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/Lookup.h" -#include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/PrettyDeclStackTrace.h" -#include "RAIIObjectsForParser.h" +#include "clang/Sema/Scope.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" @@ -36,13 +38,16 @@ using namespace clang; TypeResult Parser::ParseTypeName(SourceRange *Range, Declarator::TheContext Context, AccessSpecifier AS, - Decl **OwnedType) { + Decl **OwnedType, + ParsedAttributes *Attrs) { DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context); if (DSC == DSC_normal) DSC = DSC_type_specifier; // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); + if (Attrs) + DS.addAttributes(Attrs->getList()); ParseSpecifierQualifierList(DS, AS, DSC); if (OwnedType) *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0; @@ -209,6 +214,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation ParmLoc; bool BuiltinType = false; + TypeResult T; + SourceRange TypeRange; + bool TypeParsed = false; + switch (Tok.getKind()) { case tok::kw_char: case tok::kw_wchar_t: @@ -227,12 +236,17 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, case tok::kw_void: case tok::kw_typeof: // __attribute__(( vec_type_hint(char) )) - // FIXME: Don't just discard the builtin type token. - ConsumeToken(); BuiltinType = true; + T = ParseTypeName(&TypeRange); + TypeParsed = true; break; case tok::identifier: + if (AttrName->isStr("vec_type_hint")) { + T = ParseTypeName(&TypeRange); + TypeParsed = true; + break; + } ParmName = Tok.getIdentifierInfo(); ParmLoc = ConsumeToken(); break; @@ -242,8 +256,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, } ExprVector ArgExprs; + bool isInvalid = false; + bool isParmType = false; - if (!BuiltinType && + if (!BuiltinType && !AttrName->isStr("vec_type_hint") && (ParmLoc.isValid() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren))) { // Eat the comma. if (ParmLoc.isValid()) @@ -278,17 +294,32 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, Diag(Tok, diag::err_iboutletcollection_with_protocol); SkipUntil(tok::r_paren, false, true); // skip until ')' } + } else if (AttrName->isStr("vec_type_hint")) { + if (T.get() && !T.isInvalid()) + isParmType = true; + else { + if (Tok.is(tok::identifier)) + ConsumeToken(); + if (TypeParsed) + isInvalid = true; + } } SourceLocation RParen = Tok.getLocation(); - if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) { + if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen) && + !isInvalid) { SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc; - AttributeList *attr = - Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), - ScopeName, ScopeLoc, ParmName, ParmLoc, - ArgExprs.data(), ArgExprs.size(), Syntax); - if (BuiltinType && attr->getKind() == AttributeList::AT_IBOutletCollection) - Diag(Tok, diag::err_iboutletcollection_builtintype); + if (isParmType) { + Attrs.addNewTypeAttr(AttrName, SourceRange(AttrLoc, RParen), ScopeName, + ScopeLoc, ParmName, ParmLoc, T.get(), Syntax); + } else { + AttributeList *attr = Attrs.addNew( + AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, ParmName, + ParmLoc, ArgExprs.data(), ArgExprs.size(), Syntax); + if (BuiltinType && + attr->getKind() == AttributeList::AT_IBOutletCollection) + Diag(Tok, diag::err_iboutletcollection_builtintype); + } } } @@ -457,12 +488,11 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) || Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) || - Tok.is(tok::kw___ptr32) || - Tok.is(tok::kw___unaligned)) { + Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_MSTypespec); + SourceLocation(), 0, 0, AttributeList::AS_Keyword); } } @@ -472,21 +502,23 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_MSTypespec); + SourceLocation(), 0, 0, AttributeList::AS_Keyword); } } void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) { // Treat these like attributes while (Tok.is(tok::kw___kernel)) { + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(PP.getIdentifierInfo("opencl_kernel_function"), - AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, AttributeList::AS_GNU); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0, AttributeList::AS_Keyword); } } void Parser::ParseOpenCLQualifiers(DeclSpec &DS) { + // FIXME: The mapping from attribute spelling to semantics should be + // performed in Sema, not here. SourceLocation Loc = Tok.getLocation(); switch(Tok.getKind()) { // OpenCL qualifiers: @@ -568,7 +600,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { // Parse the major version. unsigned AfterMajor = 0; unsigned Major = 0; - while (AfterMajor < ActualLength && isdigit(ThisTokBegin[AfterMajor])) { + while (AfterMajor < ActualLength && isDigit(ThisTokBegin[AfterMajor])) { Major = Major * 10 + ThisTokBegin[AfterMajor] - '0'; ++AfterMajor; } @@ -600,7 +632,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { // Parse the minor version. unsigned AfterMinor = AfterMajor + 1; unsigned Minor = 0; - while (AfterMinor < ActualLength && isdigit(ThisTokBegin[AfterMinor])) { + while (AfterMinor < ActualLength && isDigit(ThisTokBegin[AfterMinor])) { Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0'; ++AfterMinor; } @@ -627,7 +659,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { // Parse the subminor version. unsigned AfterSubminor = AfterMinor + 1; unsigned Subminor = 0; - while (AfterSubminor < ActualLength && isdigit(ThisTokBegin[AfterSubminor])) { + while (AfterSubminor < ActualLength && isDigit(ThisTokBegin[AfterSubminor])) { Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0'; ++AfterSubminor; } @@ -735,7 +767,8 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, ConsumeToken(); if (Keyword == Ident_message) { if (!isTokenStringLiteral()) { - Diag(Tok, diag::err_expected_string_literal); + Diag(Tok, diag::err_expected_string_literal) + << /*Source='availability attribute'*/2; SkipUntil(tok::r_paren); return; } @@ -898,9 +931,11 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, LA.Toks.push_back(Tok); PP.EnterTokenStream(LA.Toks.data(), LA.Toks.size(), true, false); // Consume the previously pushed token. - ConsumeAnyToken(); + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) { + // FIXME: Do not warn on C++11 attributes, once we start supporting + // them here. Diag(Tok, diag::warn_attribute_on_function_definition) << LA.AttrName.getName(); } @@ -969,7 +1004,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, /// \brief Wrapper around a case statement checking if AttrName is /// one of the thread safety attributes -bool Parser::IsThreadSafetyAttribute(llvm::StringRef AttrName){ +bool Parser::IsThreadSafetyAttribute(StringRef AttrName) { return llvm::StringSwitch<bool>(AttrName) .Case("guarded_by", true) .Case("guarded_var", true) @@ -1018,6 +1053,7 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName, // now parse the list of expressions while (Tok.isNot(tok::r_paren)) { + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); ExprResult ArgExpr(ParseAssignmentExpression()); if (ArgExpr.isInvalid()) { ArgExprsOk = false; @@ -1137,6 +1173,25 @@ bool Parser::DiagnoseProhibitedCXX11Attribute() { llvm_unreachable("All cases handled above."); } +/// \brief We have found the opening square brackets of a C++11 +/// attribute-specifier in a location where an attribute is not permitted, but +/// we know where the attributes ought to be written. Parse them anyway, and +/// provide a fixit moving them to the right place. +void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, + SourceLocation CorrectLocation) { + assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) || + Tok.is(tok::kw_alignas)); + + // Consume the attributes. + SourceLocation Loc = Tok.getLocation(); + ParseCXX11Attributes(Attrs); + CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true); + + Diag(Loc, diag::err_attributes_not_allowed) + << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) + << FixItHint::CreateRemoval(AttrRange); +} + void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range; @@ -1145,8 +1200,8 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) { AttributeList *AttrList = attrs.getList(); while (AttrList) { - if (AttrList->isCXX0XAttribute()) { - Diag(AttrList->getLoc(), diag::warn_attribute_no_decl) + if (AttrList->isCXX11Attribute()) { + Diag(AttrList->getLoc(), diag::err_attribute_not_type_attr) << AttrList->getName(); AttrList->setInvalid(); } @@ -1239,11 +1294,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context, SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs, + ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI) { // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); - DS.takeAttributesFrom(attrs); ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, getDeclSpecContextFromDeclaratorContext(Context)); @@ -1251,6 +1305,7 @@ Parser::ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context, // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { + ProhibitAttributes(Attrs); DeclEnd = Tok.getLocation(); if (RequireSemi) ConsumeToken(); Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, @@ -1259,6 +1314,7 @@ Parser::ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context, return Actions.ConvertDeclToDeclGroup(TheDecl); } + DS.takeAttributesFrom(Attrs); return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd, FRI); } @@ -1283,7 +1339,7 @@ bool Parser::MightBeDeclarator(unsigned Context) { return getLangOpts().CPlusPlus; case tok::l_square: // Might be an attribute on an unnamed bit-field. - return Context == Declarator::MemberContext && getLangOpts().CPlusPlus0x && + return Context == Declarator::MemberContext && getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square); case tok::colon: // Might be a typo for '::' or an unnamed bit-field. @@ -1317,7 +1373,7 @@ bool Parser::MightBeDeclarator(unsigned Context) { (getLangOpts().CPlusPlus && Context == Declarator::FileContext); case tok::identifier: // Possible virt-specifier. - return getLangOpts().CPlusPlus0x && isCXX0XVirtSpecifier(NextToken()); + return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken()); default: return false; @@ -1720,7 +1776,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, Actions.AddInitializerToDecl(ThisDecl, Initializer.take(), /*DirectInit=*/true, TypeContainsAuto); } - } else if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace) && + } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) && (!CurParsedObjCImpl || !D.isFunctionDeclarator())) { // Parse C++0x braced-init-list. Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); @@ -1841,7 +1897,8 @@ static bool isValidAfterIdentifierInDeclarator(const Token &T) { /// bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, const ParsedTemplateInfo &TemplateInfo, - AccessSpecifier AS, DeclSpecContext DSC) { + AccessSpecifier AS, DeclSpecContext DSC, + ParsedAttributesWithRange &Attrs) { assert(Tok.is(tok::identifier) && "should have identifier"); SourceLocation Loc = Tok.getLocation(); @@ -1927,7 +1984,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSC_normal); else ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS, - /*EnteringContext*/ false, DSC_normal); + /*EnteringContext*/ false, DSC_normal, Attrs); return true; } } @@ -2056,7 +2113,7 @@ ExprResult Parser::ParseAlignArgument(SourceLocation Start, } else ER = ParseConstantExpression(); - if (getLangOpts().CPlusPlus0x && Tok.is(tok::ellipsis)) + if (getLangOpts().CPlusPlus11 && Tok.is(tok::ellipsis)) EllipsisLoc = ConsumeToken(); return ER; @@ -2068,15 +2125,15 @@ ExprResult Parser::ParseAlignArgument(SourceLocation Start, /// alignment-specifier: /// [C11] '_Alignas' '(' type-id ')' /// [C11] '_Alignas' '(' constant-expression ')' -/// [C++0x] 'alignas' '(' type-id ...[opt] ')' -/// [C++0x] 'alignas' '(' assignment-expression ...[opt] ')' +/// [C++11] 'alignas' '(' type-id ...[opt] ')' +/// [C++11] 'alignas' '(' assignment-expression ...[opt] ')' void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, - SourceLocation *endLoc) { + SourceLocation *EndLoc) { assert((Tok.is(tok::kw_alignas) || Tok.is(tok::kw__Alignas)) && "Not an alignment-specifier!"); - SourceLocation KWLoc = Tok.getLocation(); - ConsumeToken(); + IdentifierInfo *KWName = Tok.getIdentifierInfo(); + SourceLocation KWLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); if (T.expectAndConsume(diag::err_expected_lparen)) @@ -2090,23 +2147,13 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, } T.consumeClose(); - if (endLoc) - *endLoc = T.getCloseLocation(); - - // FIXME: Handle pack-expansions here. - if (EllipsisLoc.isValid()) { - Diag(EllipsisLoc, diag::err_alignas_pack_exp_unsupported); - return; - } + if (EndLoc) + *EndLoc = T.getCloseLocation(); ExprVector ArgExprs; ArgExprs.push_back(ArgExpr.release()); - // FIXME: This should not be GNU, but we since the attribute used is - // based on the spelling, and there is no true spelling for - // C++11 attributes, this isn't accepted. - Attrs.addNew(PP.getIdentifierInfo("aligned"), KWLoc, 0, KWLoc, - 0, T.getOpenLocation(), ArgExprs.data(), 1, - AttributeList::AS_GNU); + Attrs.addNew(KWName, KWLoc, 0, KWLoc, 0, T.getOpenLocation(), + ArgExprs.data(), 1, AttributeList::AS_Keyword, EllipsisLoc); } /// ParseDeclarationSpecifiers @@ -2176,7 +2223,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::l_square: case tok::kw_alignas: - if (!isCXX11AttributeSpecifier()) + if (!getLangOpts().CPlusPlus11 || !isCXX11AttributeSpecifier()) goto DoneWithDeclSpec; ProhibitAttributes(attrs); @@ -2270,8 +2317,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // name, then the code is ill-formed; this interpretation is // reinforced by the NAD status of core issue 635. TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next); - if ((DSContext == DSC_top_level || - (DSContext == DSC_class && DS.isFriendSpecified())) && + if ((DSContext == DSC_top_level || DSContext == DSC_class) && TemplateId->Name && Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) { if (isConstructorDeclarator()) { @@ -2321,8 +2367,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If we're in a context where the identifier could be a class name, // check whether this is a constructor declaration. - if ((DSContext == DSC_top_level || - (DSContext == DSC_class && DS.isFriendSpecified())) && + if ((DSContext == DSC_top_level || DSContext == DSC_class) && Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(), &SS)) { if (isConstructorDeclarator()) @@ -2351,7 +2396,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // typename. if (TypeRep == 0) { ConsumeToken(); // Eat the scope spec so the identifier is current. - if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext)) continue; + ParsedAttributesWithRange Attrs(AttrFactory); + if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) { + if (!Attrs.empty()) { + AttrsLastTime = true; + attrs.takeAllFrom(Attrs); + } + continue; + } goto DoneWithDeclSpec; } @@ -2447,7 +2499,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If this is not a typedef name, don't parse it as part of the declspec, // it must be an implicit int or an error. if (!TypeRep) { - if (ParseImplicitInt(DS, 0, TemplateInfo, AS, DSContext)) continue; + ParsedAttributesWithRange Attrs(AttrFactory); + if (ParseImplicitInt(DS, 0, TemplateInfo, AS, DSContext, Attrs)) { + if (!Attrs.empty()) { + AttrsLastTime = true; + attrs.takeAllFrom(Attrs); + } + continue; + } goto DoneWithDeclSpec; } @@ -2512,7 +2571,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Microsoft single token adornments. case tok::kw___forceinline: { - isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID); + isInvalid = DS.setFunctionSpecInline(Loc); IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = Tok.getLocation(); // FIXME: This does not work correctly if it is set to be a declspec @@ -2565,7 +2624,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, PrevSpec, DiagID); break; case tok::kw_auto: - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, PrevSpec, DiagID); @@ -2593,13 +2652,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // function-specifier case tok::kw_inline: - isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID); + isInvalid = DS.setFunctionSpecInline(Loc); break; case tok::kw_virtual: - isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec, DiagID); + isInvalid = DS.setFunctionSpecVirtual(Loc); break; case tok::kw_explicit: - isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID); + isInvalid = DS.setFunctionSpecExplicit(Loc); + break; + case tok::kw__Noreturn: + if (!getLangOpts().C11) + Diag(Loc, diag::ext_c11_noreturn); + isInvalid = DS.setFunctionSpecNoreturn(Loc); break; // alignment-specifier @@ -2736,6 +2800,38 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___pixel: isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); break; + case tok::kw_image1d_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_t, Loc, + PrevSpec, DiagID); + break; + case tok::kw_image1d_array_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_array_t, Loc, + PrevSpec, DiagID); + break; + case tok::kw_image1d_buffer_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_buffer_t, Loc, + PrevSpec, DiagID); + break; + case tok::kw_image2d_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_t, Loc, + PrevSpec, DiagID); + break; + case tok::kw_image2d_array_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_array_t, Loc, + PrevSpec, DiagID); + break; + case tok::kw_image3d_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image3d_t, Loc, + PrevSpec, DiagID); + break; + case tok::kw_sampler_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_sampler_t, Loc, + PrevSpec, DiagID); + break; + case tok::kw_event_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_event_t, Loc, + PrevSpec, DiagID); + break; case tok::kw___unknown_anytype: isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc, PrevSpec, DiagID); @@ -2748,8 +2844,20 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw_union: { tok::TokenKind Kind = Tok.getKind(); ConsumeToken(); + + // These are attributes following class specifiers. + // To produce better diagnostic, we parse them when + // parsing class specifier. + ParsedAttributesWithRange Attributes(AttrFactory); ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS, - EnteringContext, DSContext); + EnteringContext, DSContext, Attributes); + + // If there are attributes following class specifier, + // take them over and handle them here. + if (!Attributes.empty()) { + AttrsLastTime = true; + attrs.takeAllFrom(Attributes); + } continue; } @@ -2797,8 +2905,17 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; case tok::kw__Atomic: - ParseAtomicSpecifier(DS); - continue; + // C11 6.7.2.4/4: + // If the _Atomic keyword is immediately followed by a left parenthesis, + // it is interpreted as a type specifier (with a type name), not as a + // type qualifier. + if (NextToken().is(tok::l_paren)) { + ParseAtomicSpecifier(DS); + continue; + } + isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID, + getLangOpts()); + break; // OpenCL qualifiers: case tok::kw_private: @@ -2949,6 +3066,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, unsigned TagType, Decl *TagDecl) { PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc, "parsing struct/union body"); + assert(!getLangOpts().CPlusPlus && "C++ declarations not supported"); BalancedDelimiterTracker T(*this, tok::l_brace); if (T.consumeOpen()) @@ -2957,9 +3075,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); - // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in - // C++. - if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) { + // Empty structs are an extension in C (C99 6.7.2.1p7). + if (Tok.is(tok::r_brace)) { Diag(Tok, diag::ext_empty_struct_union) << (TagType == TST_union); Diag(Tok, diag::warn_empty_struct_union_compat) << (TagType == TST_union); } @@ -2976,6 +3093,13 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, continue; } + // Parse _Static_assert declaration. + if (Tok.is(tok::kw__Static_assert)) { + SourceLocation DeclEnd; + ParseStaticAssertDeclaration(DeclEnd); + continue; + } + if (!Tok.is(tok::at)) { struct CFieldCallback : FieldCallback { Parser &P; @@ -3093,7 +3217,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // If attributes exist after tag, parse them. ParsedAttributesWithRange attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); // If declspecs exist after tag, parse them. while (Tok.is(tok::kw___declspec)) @@ -3103,7 +3227,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, bool IsScopedUsingClassTag = false; // In C++11, recognize 'enum class' and 'enum struct'. - if (getLangOpts().CPlusPlus0x && + if (getLangOpts().CPlusPlus11 && (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) { Diag(Tok, diag::warn_cxx98_compat_scoped_enum); IsScopedUsingClassTag = Tok.is(tok::kw_class); @@ -3115,7 +3239,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // They are allowed afterwards, though. MaybeParseGNUAttributes(attrs); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); while (Tok.is(tok::kw___declspec)) ParseMicrosoftDeclSpec(attrs); } @@ -3135,7 +3259,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, bool AllowDeclaration = DSC != DSC_trailing; bool AllowFixedUnderlyingType = AllowDeclaration && - (getLangOpts().CPlusPlus0x || getLangOpts().MicrosoftExt || + (getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt || getLangOpts().ObjC2); CXXScopeSpec &SS = DS.getTypeSpecScope(); @@ -3145,7 +3269,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType); if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), - /*EnteringContext=*/false)) + /*EnteringContext=*/true)) return; if (SS.isSet() && Tok.isNot(tok::identifier)) { @@ -3254,7 +3378,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, SourceRange Range; BaseType = ParseTypeName(&Range); - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type); } else if (!getLangOpts().ObjC2) { if (getLangOpts().CPlusPlus) @@ -3313,7 +3437,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, MultiTemplateParamsArg TParams; if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && TUK != Sema::TUK_Reference) { - if (!getLangOpts().CPlusPlus0x || !SS.isSet()) { + if (!getLangOpts().CPlusPlus11 || !SS.isSet()) { // Skip the rest of this declarator, up until the comma or semicolon. Diag(Tok, diag::err_enum_template); SkipUntil(tok::comma, true); @@ -3433,7 +3557,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // If attributes exist after the enumerator, parse them. ParsedAttributesWithRange attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); ProhibitAttributes(attrs); SourceLocation EqualLoc; @@ -3471,12 +3595,12 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { SourceLocation CommaLoc = ConsumeToken(); if (Tok.isNot(tok::identifier)) { - if (!getLangOpts().C99 && !getLangOpts().CPlusPlus0x) + if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11) Diag(CommaLoc, getLangOpts().CPlusPlus ? diag::ext_enumerator_list_comma_cxx : diag::ext_enumerator_list_comma_c) << FixItHint::CreateRemoval(CommaLoc); - else if (getLangOpts().CPlusPlus0x) + else if (getLangOpts().CPlusPlus11) Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma) << FixItHint::CreateRemoval(CommaLoc); } @@ -3567,6 +3691,16 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { case tok::kw__Decimal128: case tok::kw___vector: + // OpenCL specific types: + case tok::kw_image1d_t: + case tok::kw_image1d_array_t: + case tok::kw_image1d_buffer_t: + case tok::kw_image2d_t: + case tok::kw_image2d_array_t: + case tok::kw_image3d_t: + case tok::kw_sampler_t: + case tok::kw_event_t: + // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: @@ -3639,6 +3773,16 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw__Decimal128: case tok::kw___vector: + // OpenCL specific types: + case tok::kw_image1d_t: + case tok::kw_image1d_array_t: + case tok::kw_image1d_buffer_t: + case tok::kw_image2d_t: + case tok::kw_image2d_array_t: + case tok::kw_image3d_t: + case tok::kw_sampler_t: + case tok::kw_event_t: + // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: @@ -3652,6 +3796,9 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_volatile: case tok::kw_restrict: + // Debugger support. + case tok::kw___unknown_anytype: + // typedef-name case tok::annot_typename: return true; @@ -3683,7 +3830,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_private: return getLangOpts().OpenCL; - // C11 _Atomic() + // C11 _Atomic case tok::kw__Atomic: return true; } @@ -3751,6 +3898,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { // Modules case tok::kw___module_private__: + // Debugger support + case tok::kw___unknown_anytype: + // type-specifiers case tok::kw_short: case tok::kw_long: @@ -3777,6 +3927,16 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw__Decimal128: case tok::kw___vector: + // OpenCL specific types: + case tok::kw_image1d_t: + case tok::kw_image1d_array_t: + case tok::kw_image1d_buffer_t: + case tok::kw_image2d_t: + case tok::kw_image2d_array_t: + case tok::kw_image3d_t: + case tok::kw_sampler_t: + case tok::kw_event_t: + // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: @@ -3794,6 +3954,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_inline: case tok::kw_virtual: case tok::kw_explicit: + case tok::kw__Noreturn: + + // alignment-specifier + case tok::kw__Alignas: // friend keyword. case tok::kw_friend: @@ -3811,7 +3975,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::annot_decltype: case tok::kw_constexpr: - // C11 _Atomic() + // C11 _Atomic case tok::kw__Atomic: return true; @@ -3946,13 +4110,14 @@ bool Parser::isConstructorDeclarator() { /// [vendor] type-qualifier-list attributes /// [ only if VendorAttributesAllowed=true ] /// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq -/// [ only if CXX0XAttributesAllowed=true ] +/// [ only if CXX11AttributesAllowed=true ] /// Note: vendor can be GNU, MS, etc. /// void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool VendorAttributesAllowed, - bool CXX11AttributesAllowed) { - if (getLangOpts().CPlusPlus0x && CXX11AttributesAllowed && + bool CXX11AttributesAllowed, + bool AtomicAllowed) { + if (getLangOpts().CPlusPlus11 && CXX11AttributesAllowed && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); ParseCXX11Attributes(attrs); @@ -3984,6 +4149,12 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, getLangOpts()); break; + case tok::kw__Atomic: + if (!AtomicAllowed) + goto DoneWithTypeQuals; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID, + getLangOpts()); + break; // OpenCL qualifiers: case tok::kw_private: @@ -4107,7 +4278,11 @@ void Parser::ParseDeclaratorInternal(Declarator &D, if (SS.isNotEmpty()) { if (Tok.isNot(tok::star)) { // The scope spec really belongs to the direct-declarator. - D.getCXXScopeSpec() = SS; + if (D.mayHaveIdentifier()) + D.getCXXScopeSpec() = SS; + else + AnnotateScopeToken(SS, true); + if (DirectDeclParser) (this->*DirectDeclParser)(D); return; @@ -4176,7 +4351,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Complain about rvalue references in C++03, but then go on and build // the declarator. if (Kind == tok::ampamp) - Diag(Loc, getLangOpts().CPlusPlus0x ? + Diag(Loc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_rvalue_reference : diag::ext_rvalue_reference); @@ -4194,6 +4369,10 @@ void Parser::ParseDeclaratorInternal(Declarator &D, if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) Diag(DS.getVolatileSpecLoc(), diag::err_invalid_reference_qualifier_application) << "volatile"; + // 'restrict' is permitted as an extension. + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) + Diag(DS.getAtomicSpecLoc(), + diag::err_invalid_reference_qualifier_application) << "_Atomic"; } // Recursively parse the declarator. @@ -4216,7 +4395,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, } } - // Remember that we parsed a reference type. It doesn't have type-quals. + // Remember that we parsed a reference type. D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, Kind == tok::amp), DS.getAttributes(), @@ -4308,6 +4487,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { !((D.getContext() == Declarator::PrototypeContext || D.getContext() == Declarator::BlockLiteralContext) && NextToken().is(tok::r_paren) && + !D.hasGroupingParens() && !Actions.containsUnexpandedParameterPacks(D))) { SourceLocation EllipsisLoc = ConsumeToken(); if (isPtrOperatorToken(Tok.getKind(), getLangOpts())) { @@ -4334,8 +4514,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { else if (D.getCXXScopeSpec().isSet()) AllowConstructorName = (D.getContext() == Declarator::FileContext || - (D.getContext() == Declarator::MemberContext && - D.getDeclSpec().isFriendSpecified())); + D.getContext() == Declarator::MemberContext); else AllowConstructorName = (D.getContext() == Declarator::MemberContext); @@ -4391,15 +4570,24 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // This could be something simple like "int" (in which case the declarator // portion is empty), if an abstract-declarator is allowed. D.SetIdentifier(0, Tok.getLocation()); + + // The grammar for abstract-pack-declarator does not allow grouping parens. + // FIXME: Revisit this once core issue 1488 is resolved. + if (D.hasEllipsis() && D.hasGroupingParens()) + Diag(PP.getLocForEndOfToken(D.getEllipsisLoc()), + diag::ext_abstract_pack_declarator_parens); } else { if (Tok.getKind() == tok::annot_pragma_parser_crash) LLVM_BUILTIN_TRAP; if (D.getContext() == Declarator::MemberContext) Diag(Tok, diag::err_expected_member_name_or_semi) << D.getDeclSpec().getSourceRange(); - else if (getLangOpts().CPlusPlus) - Diag(Tok, diag::err_expected_unqualified_id) << getLangOpts().CPlusPlus; - else + else if (getLangOpts().CPlusPlus) { + if (Tok.is(tok::period) || Tok.is(tok::arrow)) + Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow); + else + Diag(Tok, diag::err_expected_unqualified_id) << getLangOpts().CPlusPlus; + } else Diag(Tok, diag::err_expected_ident_lparen); D.SetIdentifier(0, Tok.getLocation()); D.setInvalidType(true); @@ -4411,14 +4599,17 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // Don't parse attributes unless we have parsed an unparenthesized name. if (D.hasName() && !D.getNumTypeObjects()) - MaybeParseCXX0XAttributes(D); + MaybeParseCXX11Attributes(D); while (1) { if (Tok.is(tok::l_paren)) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); + Scope::FunctionPrototypeScope|Scope::DeclScope| + (D.isFunctionDeclaratorAFunctionDeclaration() + ? Scope::FunctionDeclarationScope : 0)); + // The paren may be part of a C++ direct initializer, eg. "int x(1);". // In such a case, check if we actually have a function declarator; if it // is not, the declarator has been fully parsed. @@ -4483,13 +4674,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { // present even if the attribute list was empty. RequiresArg = true; } + // Eat any Microsoft extensions. - if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) || - Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___fastcall) || - Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64) || - Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned)) { - ParseMicrosoftTypeAttributes(attrs); - } + ParseMicrosoftTypeAttributes(attrs); + // Eat any Borland extensions. if (Tok.is(tok::kw___pascal)) ParseBorlandTypeAttributes(attrs); @@ -4551,7 +4739,9 @@ void Parser::ParseParenDeclarator(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); + Scope::FunctionPrototypeScope | Scope::DeclScope | + (D.isFunctionDeclaratorAFunctionDeclaration() + ? Scope::FunctionDeclarationScope : 0)); ParseFunctionDeclarator(D, attrs, T, false, RequiresArg); PrototypeScope.Exit(); } @@ -4646,7 +4836,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // with the virt-specifier-seq and pure-specifier in the same way. // Parse cv-qualifier-seq[opt]. - ParseTypeQualifierListOpt(DS, false /*no attributes*/, false); + ParseTypeQualifierListOpt(DS, /*VendorAttributesAllowed*/ false, + /*CXX11AttributesAllowed*/ false, + /*AtomicAllowed*/ false); if (!DS.getSourceRange().getEnd().isInvalid()) { EndLoc = DS.getSourceRange().getEnd(); ConstQualifierLoc = DS.getConstSpecLoc(); @@ -4655,7 +4847,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // Parse ref-qualifier[opt]. if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { - Diag(Tok, getLangOpts().CPlusPlus0x ? + Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_ref_qualifier : diag::ext_ref_qualifier); @@ -4670,15 +4862,19 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq // and the end of the function-definition, member-declarator, or // declarator. + // FIXME: currently, "static" case isn't handled correctly. bool IsCXX11MemberFunction = - getLangOpts().CPlusPlus0x && - (D.getContext() == Declarator::MemberContext || - (D.getContext() == Declarator::FileContext && - D.getCXXScopeSpec().isValid() && - Actions.CurContext->isRecord())); + getLangOpts().CPlusPlus11 && + (D.getContext() == Declarator::MemberContext + ? !D.getDeclSpec().isFriendSpecified() + : D.getContext() == Declarator::FileContext && + D.getCXXScopeSpec().isValid() && + Actions.CurContext->isRecord()); Sema::CXXThisScopeRAII ThisScope(Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), - DS.getTypeQualifiers(), + DS.getTypeQualifiers() | + (D.getDeclSpec().isConstexprSpecified() + ? Qualifiers::Const : 0), IsCXX11MemberFunction); // Parse exception-specification[opt]. @@ -4691,11 +4887,11 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // Parse attribute-specifier-seq[opt]. Per DR 979 and DR 1297, this goes // after the exception-specification. - MaybeParseCXX0XAttributes(FnAttrs); + MaybeParseCXX11Attributes(FnAttrs); // Parse trailing-return-type[opt]. LocalEndLoc = EndLoc; - if (getLangOpts().CPlusPlus0x && Tok.is(tok::arrow)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::arrow)) { Diag(Tok, diag::warn_cxx98_compat_trailing_return_type); if (D.getDeclSpec().getTypeSpecType() == TST_auto) StartLoc = D.getDeclSpec().getTypeSpecTypeLoc(); @@ -4866,11 +5062,10 @@ void Parser::ParseParameterDeclarationClause( DeclSpec DS(AttrFactory); // Parse any C++11 attributes. - MaybeParseCXX0XAttributes(DS.getAttributes()); + MaybeParseCXX11Attributes(DS.getAttributes()); // Skip any Microsoft attributes before a param. - if (getLangOpts().MicrosoftExt && Tok.is(tok::l_square)) - ParseMicrosoftAttributes(DS.getAttributes()); + MaybeParseMicrosoftAttributes(DS.getAttributes()); SourceLocation DSStart = Tok.getLocation(); @@ -4955,7 +5150,7 @@ void Parser::ParseParameterDeclarationClause( Param); ExprResult DefArgResult; - if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); DefArgResult = ParseBraceInitializer(); } else @@ -5017,7 +5212,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { if (Tok.getKind() == tok::r_square) { T.consumeClose(); ParsedAttributes attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); // Remember that we parsed the empty array type. ExprResult NumElements; @@ -5034,10 +5229,10 @@ void Parser::ParseBracketDeclarator(Declarator &D) { T.consumeClose(); ParsedAttributes attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.release(), T.getOpenLocation(), T.getCloseLocation()), @@ -5104,7 +5299,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { T.consumeClose(); ParsedAttributes attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), @@ -5184,14 +5379,13 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { /// _Atomic ( type-name ) /// void Parser::ParseAtomicSpecifier(DeclSpec &DS) { - assert(Tok.is(tok::kw__Atomic) && "Not an atomic specifier"); + assert(Tok.is(tok::kw__Atomic) && NextToken().is(tok::l_paren) && + "Not an atomic specifier"); SourceLocation StartLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, "_Atomic")) { - SkipUntil(tok::r_paren); + if (T.consumeOpen()) return; - } TypeResult Result = ParseTypeName(); if (Result.isInvalid()) { diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index f11a9d1..d7f8e98 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -11,16 +11,17 @@ // //===----------------------------------------------------------------------===// -#include "clang/Basic/OperatorKinds.h" #include "clang/Parse/Parser.h" +#include "RAIIObjectsForParser.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/OperatorKinds.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/PrettyDeclStackTrace.h" +#include "clang/Sema/Scope.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallString.h" -#include "RAIIObjectsForParser.h" using namespace clang; /// ParseNamespace - We know that the current token is a namespace keyword. This @@ -157,7 +158,7 @@ Decl *Parser::ParseNamespace(unsigned Context, // If we're still good, complain about inline namespaces in non-C++0x now. if (InlineLoc.isValid()) - Diag(InlineLoc, getLangOpts().CPlusPlus0x ? + Diag(InlineLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_inline_namespace : diag::ext_inline_namespace); // Enter a scope for the namespace. @@ -195,7 +196,7 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, if (index == Ident.size()) { while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); ParseExternalDeclaration(attrs); } @@ -295,7 +296,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { : SourceLocation()); ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); if (Tok.isNot(tok::l_brace)) { @@ -318,7 +319,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { T.consumeOpen(); while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); ParseExternalDeclaration(attrs); } @@ -439,8 +440,8 @@ Decl *Parser::ParseUsingDirective(unsigned Context, /// unqualified-id /// 'using' :: unqualified-id /// -/// alias-declaration: C++0x [decl.typedef]p2 -/// 'using' identifier = type-id ; +/// alias-declaration: C++11 [dcl.dcl]p1 +/// 'using' identifier attribute-specifier-seq[opt] = type-id ; /// Decl *Parser::ParseUsingDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, @@ -450,27 +451,27 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, Decl **OwnedType) { CXXScopeSpec SS; SourceLocation TypenameLoc; - bool IsTypeName; - ParsedAttributesWithRange attrs(AttrFactory); + bool IsTypeName = false; + ParsedAttributesWithRange Attrs(AttrFactory); // FIXME: Simply skip the attributes and diagnose, don't bother parsing them. - MaybeParseCXX0XAttributes(attrs); - ProhibitAttributes(attrs); - attrs.clear(); - attrs.Range = SourceRange(); + MaybeParseCXX11Attributes(Attrs); + ProhibitAttributes(Attrs); + Attrs.clear(); + Attrs.Range = SourceRange(); // Ignore optional 'typename'. // FIXME: This is wrong; we should parse this as a typename-specifier. if (Tok.is(tok::kw_typename)) { - TypenameLoc = Tok.getLocation(); - ConsumeToken(); + TypenameLoc = ConsumeToken(); IsTypeName = true; } - else - IsTypeName = false; // Parse nested-name-specifier. - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + IdentifierInfo *LastII = 0; + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false, + /*MayBePseudoDtor=*/0, /*IsTypename=*/false, + /*LastII=*/&LastII); // Check nested-name specifier. if (SS.isInvalid()) { @@ -478,33 +479,45 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + // Parse the unqualified-id. We allow parsing of both constructor and // destructor names and allow the action module to diagnose any semantic // errors. - SourceLocation TemplateKWLoc; - UnqualifiedId Name; - if (ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/true, - /*AllowConstructorName=*/true, - ParsedType(), - TemplateKWLoc, - Name)) { + // + // C++11 [class.qual]p2: + // [...] in a using-declaration that is a member-declaration, if the name + // specified after the nested-name-specifier is the same as the identifier + // or the simple-template-id's template-name in the last component of the + // nested-name-specifier, the name is [...] considered to name the + // constructor. + if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext && + Tok.is(tok::identifier) && NextToken().is(tok::semi) && + SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && + !SS.getScopeRep()->getAsNamespace() && + !SS.getScopeRep()->getAsNamespaceAlias()) { + SourceLocation IdLoc = ConsumeToken(); + ParsedType Type = Actions.getInheritingConstructorName(SS, IdLoc, *LastII); + Name.setConstructorName(Type, IdLoc, IdLoc); + } else if (ParseUnqualifiedId(SS, /*EnteringContext=*/ false, + /*AllowDestructorName=*/ true, + /*AllowConstructorName=*/ true, ParsedType(), + TemplateKWLoc, Name)) { SkipUntil(tok::semi); return 0; } - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(Attrs); // Maybe this is an alias-declaration. bool IsAliasDecl = Tok.is(tok::equal); TypeResult TypeAlias; if (IsAliasDecl) { - // TODO: Attribute support. C++0x attributes may appear before the equals. - // Where can GNU attributes appear? + // TODO: Can GNU attributes appear here? ConsumeToken(); - Diag(Tok.getLocation(), getLangOpts().CPlusPlus0x ? + Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_alias_declaration : diag::ext_alias_declaration); @@ -546,25 +559,26 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, TypeAlias = ParseTypeName(0, TemplateInfo.Kind ? Declarator::AliasTemplateContext : - Declarator::AliasDeclContext, AS, OwnedType); + Declarator::AliasDeclContext, AS, OwnedType, + &Attrs); } else { // C++11 attributes are not allowed on a using-declaration, but GNU ones // are. - ProhibitAttributes(attrs); + ProhibitAttributes(Attrs); // Parse (optional) attributes (most likely GNU strong-using extension). - MaybeParseGNUAttributes(attrs); + MaybeParseGNUAttributes(Attrs); } // Eat ';'. DeclEnd = Tok.getLocation(); ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - !attrs.empty() ? "attributes list" : + !Attrs.empty() ? "attributes list" : IsAliasDecl ? "alias declaration" : "using declaration", tok::semi); // Diagnose an attempt to declare a templated using-declaration. - // In C++0x, alias-declarations can be templates: + // In C++11, alias-declarations can be templates: // template <...> using id = type; if (TemplateInfo.Kind && !IsAliasDecl) { SourceRange R = TemplateInfo.getSourceRange(); @@ -591,13 +605,13 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, MultiTemplateParamsArg TemplateParamsArg( TemplateParams ? TemplateParams->data() : 0, TemplateParams ? TemplateParams->size() : 0); - // FIXME: Propagate attributes. return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, - UsingLoc, Name, TypeAlias); + UsingLoc, Name, Attrs.getList(), + TypeAlias); } return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS, - Name, attrs.getList(), + Name, Attrs.getList(), IsTypeName, TypenameLoc); } @@ -637,7 +651,8 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ return 0; if (!isTokenStringLiteral()) { - Diag(Tok, diag::err_expected_string_literal); + Diag(Tok, diag::err_expected_string_literal) + << /*Source='static_assert'*/1; SkipMalformedDecl(); return 0; } @@ -800,15 +815,18 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { /// class. The result is either a type or null, depending on whether a type /// name was found. /// -/// base-type-specifier: [C++ 10.1] +/// base-type-specifier: [C++11 class.derived] /// class-or-decltype -/// class-or-decltype: [C++ 10.1] +/// class-or-decltype: [C++11 class.derived] /// nested-name-specifier[opt] class-name /// decltype-specifier -/// class-name: [C++ 9.1] +/// class-name: [C++ class.name] /// identifier /// simple-template-id /// +/// In C++98, instead of base-type-specifier, we have: +/// +/// ::[opt] nested-name-specifier[opt] class-name Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, SourceLocation &EndLocation) { // Ignore attempts to use typename @@ -956,6 +974,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::semi: // struct foo {...} ; case tok::star: // struct foo {...} * P; case tok::amp: // struct foo {...} & R = ... + case tok::ampamp: // struct foo {...} && R = ... case tok::identifier: // struct foo {...} V ; case tok::r_paren: //(struct foo {...} ) {4} case tok::annot_cxxscope: // struct foo {...} a:: b; @@ -963,6 +982,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::annot_template_id: // struct foo {...} a<int> ::b; case tok::l_paren: // struct foo {...} ( x); case tok::comma: // __builtin_offsetof(struct foo{...} , + case tok::kw_operator: // struct foo operator ++() {...} return true; case tok::colon: return CouldBeBitfield; // enum E { ... } : 2; @@ -970,7 +990,12 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::kw_const: // struct foo {...} const x; case tok::kw_volatile: // struct foo {...} volatile x; case tok::kw_restrict: // struct foo {...} restrict x; - case tok::kw_inline: // struct foo {...} inline foo() {}; + // Function specifiers + // Note, no 'explicit'. An explicit function must be either a conversion + // operator or a constructor. Either way, it can't have a return type. + case tok::kw_inline: // struct foo inline f(); + case tok::kw_virtual: // struct foo virtual f(); + case tok::kw_friend: // struct foo friend f(); // Storage-class specifiers case tok::kw_static: // struct foo {...} static x; case tok::kw_extern: // struct foo {...} extern x; @@ -978,6 +1003,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::kw_register: // struct foo {...} register x; case tok::kw_auto: // struct foo {...} auto x; case tok::kw_mutable: // struct foo {...} mutable x; + case tok::kw_thread_local: // struct foo {...} thread_local x; case tok::kw_constexpr: // struct foo {...} constexpr x; // As shown above, type qualifiers and storage class specifiers absolutely // can occur after class specifiers according to the grammar. However, @@ -1002,6 +1028,13 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { if (!getLangOpts().CPlusPlus) return true; break; + // C++11 attributes + case tok::l_square: // enum E [[]] x + // Note, no tok::kw_alignas here; alignas cannot appertain to a type. + return getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square); + case tok::greater: + // template<class T = class X> + return getLangOpts().CPlusPlus; } return false; } @@ -1050,7 +1083,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation StartLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, - bool EnteringContext, DeclSpecContext DSC) { + bool EnteringContext, DeclSpecContext DSC, + ParsedAttributesWithRange &Attributes) { DeclSpec::TST TagType; if (TagTokKind == tok::kw_struct) TagType = DeclSpec::TST_struct; @@ -1102,7 +1136,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // If C++0x attributes exist here, parse them. // FIXME: Are we consistent with the ordering of parsing of different // styles of attributes? - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); + + // Source location used by FIXIT to insert misplaced + // C++11 attributes + SourceLocation AttrFixitLoc = Tok.getLocation(); if (TagType == DeclSpec::TST_struct && !Tok.is(tok::identifier) && @@ -1232,18 +1270,30 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // - If we have 'struct foo;', then this is either a forward declaration // or a friend declaration, which have to be treated differently. // - Otherwise we have something like 'struct foo xyz', a reference. + // + // We also detect these erroneous cases to provide better diagnostic for + // C++11 attributes parsing. + // - attributes follow class name: + // struct foo [[]] {}; + // - attributes appear before or after 'final': + // struct foo [[]] final [[]] {}; + // // However, in type-specifier-seq's, things look like declarations but are // just references, e.g. // new struct s; // or // &T::operator struct s; // For these, DSC is DSC_type_specifier. + + // If there are attributes after class name, parse them. + MaybeParseCXX11Attributes(Attributes); + Sema::TagUseKind TUK; if (DSC == DSC_trailing) TUK = Sema::TUK_Reference; else if (Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || - (isCXX0XFinalKeyword() && + (isCXX11FinalKeyword() && (NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) { if (DS.isFriendSpecified()) { // C++ [class.friend]p2: @@ -1259,6 +1309,37 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Okay, this is a class definition. TUK = Sema::TUK_Definition; } + } else if (isCXX11FinalKeyword() && (NextToken().is(tok::l_square) || + NextToken().is(tok::kw_alignas))) { + // We can't tell if this is a definition or reference + // until we skipped the 'final' and C++11 attribute specifiers. + TentativeParsingAction PA(*this); + + // Skip the 'final' keyword. + ConsumeToken(); + + // Skip C++11 attribute specifiers. + while (true) { + if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) { + ConsumeBracket(); + if (!SkipUntil(tok::r_square)) + break; + } else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) { + ConsumeToken(); + ConsumeParen(); + if (!SkipUntil(tok::r_paren)) + break; + } else { + break; + } + } + + if (Tok.is(tok::l_brace) || Tok.is(tok::colon)) + TUK = Sema::TUK_Definition; + else + TUK = Sema::TUK_Reference; + + PA.Revert(); } else if (DSC != DSC_type_specifier && (Tok.is(tok::semi) || (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) { @@ -1273,6 +1354,28 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } else TUK = Sema::TUK_Reference; + // Forbid misplaced attributes. In cases of a reference, we pass attributes + // to caller to handle. + if (TUK != Sema::TUK_Reference) { + // If this is not a reference, then the only possible + // valid place for C++11 attributes to appear here + // is between class-key and class-name. If there are + // any attributes after class-name, we try a fixit to move + // them to the right place. + SourceRange AttrRange = Attributes.Range; + if (AttrRange.isValid()) { + Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) + << AttrRange + << FixItHint::CreateInsertionFromRange(AttrFixitLoc, + CharSourceRange(AttrRange, true)) + << FixItHint::CreateRemoval(AttrRange); + + // Recover by adding misplaced attributes to the attribute list + // of the class so they can be applied on the class later. + attrs.takeAllFrom(Attributes); + } + } + // If this is an elaborated type specifier, and we delayed // diagnostics before, just merge them into the current pool. if (shouldDelayDiagsInTag) { @@ -1414,11 +1517,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateParams? &(*TemplateParams)[0] : 0, TemplateParams? TemplateParams->size() : 0)); } else { - if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && - TUK == Sema::TUK_Definition) { - // FIXME: Diagnose this particular error. - } - if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) ProhibitAttributes(attrs); @@ -1453,9 +1551,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TUK == Sema::TUK_Definition) { assert(Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || - isCXX0XFinalKeyword()); + isCXX11FinalKeyword()); if (getLangOpts().CPlusPlus) - ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get()); + ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, + TagOrTempResult.get()); else ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get()); } @@ -1490,13 +1589,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // is permitted. if (TUK == Sema::TUK_Definition && (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, - DeclSpec::getSpecifierName(TagType)); - // Push this token back into the preprocessor and change our current token - // to ';' so that the rest of the code recovers as though there were an - // ';' after the definition. - PP.EnterToken(Tok); - Tok.setKind(tok::semi); + if (Tok.isNot(tok::semi)) { + ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, + DeclSpec::getSpecifierName(TagType)); + // Push this token back into the preprocessor and change our current token + // to ';' so that the rest of the code recovers as though there were an + // ';' after the definition. + PP.EnterToken(Tok); + Tok.setKind(tok::semi); + } } } @@ -1544,26 +1645,33 @@ void Parser::ParseBaseClause(Decl *ClassDecl) { /// 'public bar' and 'virtual private baz' are each base-specifiers. /// /// base-specifier: [C++ class.derived] -/// ::[opt] nested-name-specifier[opt] class-name -/// 'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt] -/// base-type-specifier -/// access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt] -/// base-type-specifier +/// attribute-specifier-seq[opt] base-type-specifier +/// attribute-specifier-seq[opt] 'virtual' access-specifier[opt] +/// base-type-specifier +/// attribute-specifier-seq[opt] access-specifier 'virtual'[opt] +/// base-type-specifier Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { bool IsVirtual = false; SourceLocation StartLoc = Tok.getLocation(); + ParsedAttributesWithRange Attributes(AttrFactory); + MaybeParseCXX11Attributes(Attributes); + // Parse the 'virtual' keyword. if (Tok.is(tok::kw_virtual)) { ConsumeToken(); IsVirtual = true; } + CheckMisplacedCXX11Attribute(Attributes, StartLoc); + // Parse an (optional) access specifier. AccessSpecifier Access = getAccessSpecifierIfPresent(); if (Access != AS_none) ConsumeToken(); + CheckMisplacedCXX11Attribute(Attributes, StartLoc); + // Parse the 'virtual' keyword (again!), in case it came after the // access specifier. if (Tok.is(tok::kw_virtual)) { @@ -1577,6 +1685,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { IsVirtual = true; } + CheckMisplacedCXX11Attribute(Attributes, StartLoc); + // Parse the class-name. SourceLocation EndLocation; SourceLocation BaseLoc; @@ -1596,8 +1706,9 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { // Notify semantic analysis that we have parsed a complete // base-specifier. - return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, - BaseType.get(), BaseLoc, EllipsisLoc); + return Actions.ActOnBaseSpecifier(ClassDecl, Range, Attributes, IsVirtual, + Access, BaseType.get(), BaseLoc, + EllipsisLoc); } /// getAccessSpecifierIfPresent - Determine whether the next token is @@ -1653,13 +1764,13 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, } } -/// isCXX0XVirtSpecifier - Determine whether the given token is a C++0x +/// isCXX11VirtSpecifier - Determine whether the given token is a C++11 /// virt-specifier. /// /// virt-specifier: /// override /// final -VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier(const Token &Tok) const { +VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const { if (!getLangOpts().CPlusPlus) return VirtSpecifiers::VS_None; @@ -1682,15 +1793,15 @@ VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier(const Token &Tok) const { return VirtSpecifiers::VS_None; } -/// ParseOptionalCXX0XVirtSpecifierSeq - Parse a virt-specifier-seq. +/// ParseOptionalCXX11VirtSpecifierSeq - Parse a virt-specifier-seq. /// /// virt-specifier-seq: /// virt-specifier /// virt-specifier-seq virt-specifier -void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS, +void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface) { while (true) { - VirtSpecifiers::Specifier Specifier = isCXX0XVirtSpecifier(); + VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(); if (Specifier == VirtSpecifiers::VS_None) return; @@ -1706,7 +1817,7 @@ void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS, Diag(Tok.getLocation(), diag::err_override_control_interface) << VirtSpecifiers::getSpecifierName(Specifier); } else { - Diag(Tok.getLocation(), getLangOpts().CPlusPlus0x ? + Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_override_control_keyword : diag::ext_override_control_keyword) << VirtSpecifiers::getSpecifierName(Specifier); @@ -1715,9 +1826,9 @@ void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS, } } -/// isCXX0XFinalKeyword - Determine whether the next token is a C++0x +/// isCXX11FinalKeyword - Determine whether the next token is a C++11 /// contextual 'final' keyword. -bool Parser::isCXX0XFinalKeyword() const { +bool Parser::isCXX11FinalKeyword() const { if (!getLangOpts().CPlusPlus) return false; @@ -1861,8 +1972,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ColonProtectionRAIIObject X(*this); ParsedAttributesWithRange attrs(AttrFactory); - // Optional C++0x attribute-specifier - MaybeParseCXX0XAttributes(attrs); + ParsedAttributesWithRange FnAttrs(AttrFactory); + // Optional C++11 attribute-specifier + MaybeParseCXX11Attributes(attrs); + // We need to keep these attributes for future diagnostic + // before they are taken over by declaration specifier. + FnAttrs.addAll(attrs.getList()); + FnAttrs.Range = attrs.Range; + MaybeParseMicrosoftAttributes(attrs); if (Tok.is(tok::kw_using)) { @@ -1901,6 +2018,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::semi)) { ConsumeToken(); + + if (DS.isFriendSpecified()) + ProhibitAttributes(FnAttrs); + Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams); DS.complete(TheDecl); @@ -1931,7 +2052,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return; } - ParseOptionalCXX0XVirtSpecifierSeq(VS, getCurrentClass().IsInterface); + ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); // If attributes exist after the declarator, but before an '{', parse them. MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); @@ -1955,7 +2076,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // In C++11, a non-function declarator followed by an open brace is a // braced-init-list for an in-class member initialization, not an // erroneous function definition. - if (Tok.is(tok::l_brace) && !getLangOpts().CPlusPlus0x) { + if (Tok.is(tok::l_brace) && !getLangOpts().CPlusPlus11) { DefinitionKind = FDK_Definition; } else if (DeclaratorInfo.isFunctionDeclarator()) { if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) { @@ -1969,12 +2090,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } } + // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains + // to a friend declaration, that declaration shall be a definition. + if (DeclaratorInfo.isFunctionDeclarator() && + DefinitionKind != FDK_Definition && DS.isFriendSpecified()) { + // Diagnose attributes that appear before decl specifier: + // [[]] friend int foo(); + ProhibitAttributes(FnAttrs); + } + if (DefinitionKind) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params); ConsumeBrace(); SkipUntil(tok::r_brace, /*StopAtSemi*/false); - + // Consume the optional ';' if (Tok.is(tok::semi)) ConsumeToken(); @@ -1984,16 +2114,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_function_declared_typedef); - // This recovery skips the entire function body. It would be nice - // to simply call ParseCXXInlineMethodDef() below, however Sema - // assumes the declarator represents a function, not a typedef. - ConsumeBrace(); - SkipUntil(tok::r_brace, /*StopAtSemi*/false); - // Consume the optional ';' - if (Tok.is(tok::semi)) - ConsumeToken(); - return; + // Recover by treating the 'typedef' as spurious. + DS.ClearStorageClassSpecs(); } Decl *FunDecl = @@ -2052,7 +2175,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // FIXME: When g++ adds support for this, we'll need to check whether it // goes before or after the GNU attributes and __asm__. - ParseOptionalCXX0XVirtSpecifierSeq(VS, getCurrentClass().IsInterface); + ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); InClassInitStyle HasInClassInit = ICIS_NoInit; if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) { @@ -2063,8 +2186,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, HasInitializer = true; if (!DeclaratorInfo.isDeclarationOfFunction() && DeclaratorInfo.getDeclSpec().getStorageClassSpec() - != DeclSpec::SCS_static && - DeclaratorInfo.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit; } @@ -2074,8 +2195,23 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // this call will *not* return the created decl; It will return null. // See Sema::ActOnCXXMemberDeclarator for details. - Decl *ThisDecl = 0; + NamedDecl *ThisDecl = 0; if (DS.isFriendSpecified()) { + // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains + // to a friend declaration, that declaration shall be a definition. + // + // Diagnose attributes appear after friend member function declarator: + // foo [[]] (); + SmallVector<SourceRange, 4> Ranges; + DeclaratorInfo.getCXX11AttributeRanges(Ranges); + if (!Ranges.empty()) { + for (SmallVector<SourceRange, 4>::iterator I = Ranges.begin(), + E = Ranges.end(); I != E; ++I) { + Diag((*I).getBegin(), diag::err_attributes_not_allowed) + << *I; + } + } + // TODO: handle initializers, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, TemplateParams); @@ -2100,9 +2236,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, LateParsedAttrs.clear(); // Handle the initializer. - if (HasInClassInit != ICIS_NoInit) { + if (HasInClassInit != ICIS_NoInit && + DeclaratorInfo.getDeclSpec().getStorageClassSpec() != + DeclSpec::SCS_static) { // The initializer was deferred; parse it and cache the tokens. - Diag(Tok, getLangOpts().CPlusPlus0x ? + Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_nonstatic_member_init : diag::ext_nonstatic_member_init); @@ -2264,6 +2402,8 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, /// access-specifier ':' member-specification[opt] /// void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, + SourceLocation AttrFixitLoc, + ParsedAttributesWithRange &Attrs, unsigned TagType, Decl *TagDecl) { assert((TagType == DeclSpec::TST_struct || TagType == DeclSpec::TST_interface || @@ -2320,17 +2460,23 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // Parse the optional 'final' keyword. if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) { - assert(isCXX0XFinalKeyword() && "not a class definition"); + assert(isCXX11FinalKeyword() && "not a class definition"); FinalLoc = ConsumeToken(); if (TagType == DeclSpec::TST_interface) { Diag(FinalLoc, diag::err_override_control_interface) << "final"; } else { - Diag(FinalLoc, getLangOpts().CPlusPlus0x ? + Diag(FinalLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_override_control_keyword : diag::ext_override_control_keyword) << "final"; } + + // Parse any C++11 attributes after 'final' keyword. + // These attributes are not allowed to appear here, + // and the only possible place for them to appertain + // to the class would be between class-key and class-name. + CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc); } if (Tok.is(tok::colon)) { @@ -2395,6 +2541,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, continue; } + if (Tok.is(tok::annot_pragma_openmp)) { + ParseOpenMPDeclarativeDirective(); + continue; + } + AccessSpecifier AS = getAccessSpecifierIfPresent(); if (AS != AS_none) { // Current token is a C++ access specifier. @@ -2551,8 +2702,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { } } while (true); - Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, - MemInitializers.data(), MemInitializers.size(), + Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, MemInitializers, AnyErrors); } @@ -2606,7 +2756,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // Parse the '('. - if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); ExprResult InitList = ParseBraceInitializer(); @@ -2645,7 +2795,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { EllipsisLoc); } - Diag(Tok, getLangOpts().CPlusPlus0x ? diag::err_expected_lparen_or_lbrace + Diag(Tok, getLangOpts().CPlusPlus11 ? diag::err_expected_lparen_or_lbrace : diag::err_expected_lparen); return true; } @@ -2892,9 +3042,9 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { case tok::exclaimequal: // 'not_eq' // Alternative tokens do not have identifier info, but their spelling // starts with an alphabetical character. - llvm::SmallString<8> SpellingBuf; + SmallString<8> SpellingBuf; StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf); - if (std::isalpha(Spelling[0])) { + if (isLetter(Spelling[0])) { Loc = ConsumeToken(); return &PP.getIdentifierTable().get(Spelling); } @@ -2908,7 +3058,7 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, AttributeList::AS_CXX11)) { case AttributeList::AT_CarriesDependency: case AttributeList::AT_FallThrough: - case AttributeList::AT_NoReturn: { + case AttributeList::AT_CXX11NoReturn: { return true; } @@ -2971,6 +3121,8 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, ConsumeBracket(); ConsumeBracket(); + llvm::SmallDenseMap<IdentifierInfo*, SourceLocation, 4> SeenAttrs; + while (Tok.isNot(tok::r_square)) { // attribute not present if (Tok.is(tok::comma)) { @@ -3004,6 +3156,11 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName,ScopeName); bool AttrParsed = false; + if (StandardAttr && + !SeenAttrs.insert(std::make_pair(AttrName, AttrLoc)).second) + Diag(AttrLoc, diag::err_cxx11_attribute_repeated) + << AttrName << SourceRange(SeenAttrs[AttrName]); + // Parse attribute arguments if (Tok.is(tok::l_paren)) { if (ScopeName && ScopeName->getName() == "gnu") { @@ -3050,6 +3207,8 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, /// attribute-specifier-seq[opt] attribute-specifier void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *endLoc) { + assert(getLangOpts().CPlusPlus11); + SourceLocation StartLoc = Tok.getLocation(), Loc; if (!endLoc) endLoc = &Loc; diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index c7be0d3..956ba36 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -22,77 +22,16 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" +#include "RAIIObjectsForParser.h" +#include "clang/Basic/PrettyStackTrace.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" -#include "clang/Basic/PrettyStackTrace.h" -#include "RAIIObjectsForParser.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" using namespace clang; -/// \brief Return the precedence of the specified binary operator token. -static prec::Level getBinOpPrecedence(tok::TokenKind Kind, - bool GreaterThanIsOperator, - bool CPlusPlus0x) { - switch (Kind) { - case tok::greater: - // C++ [temp.names]p3: - // [...] When parsing a template-argument-list, the first - // non-nested > is taken as the ending delimiter rather than a - // greater-than operator. [...] - if (GreaterThanIsOperator) - return prec::Relational; - return prec::Unknown; - - case tok::greatergreater: - // C++0x [temp.names]p3: - // - // [...] Similarly, the first non-nested >> is treated as two - // consecutive but distinct > tokens, the first of which is - // taken as the end of the template-argument-list and completes - // the template-id. [...] - if (GreaterThanIsOperator || !CPlusPlus0x) - return prec::Shift; - return prec::Unknown; - - default: return prec::Unknown; - case tok::comma: return prec::Comma; - case tok::equal: - case tok::starequal: - case tok::slashequal: - case tok::percentequal: - case tok::plusequal: - case tok::minusequal: - case tok::lesslessequal: - case tok::greatergreaterequal: - case tok::ampequal: - case tok::caretequal: - case tok::pipeequal: return prec::Assignment; - case tok::question: return prec::Conditional; - case tok::pipepipe: return prec::LogicalOr; - case tok::ampamp: return prec::LogicalAnd; - case tok::pipe: return prec::InclusiveOr; - case tok::caret: return prec::ExclusiveOr; - case tok::amp: return prec::And; - case tok::exclaimequal: - case tok::equalequal: return prec::Equality; - case tok::lessequal: - case tok::less: - case tok::greaterequal: return prec::Relational; - case tok::lessless: return prec::Shift; - case tok::plus: - case tok::minus: return prec::Additive; - case tok::percent: - case tok::slash: - case tok::star: return prec::Multiplicative; - case tok::periodstar: - case tok::arrowstar: return prec::PointerToMember; - } -} - - /// \brief Simple precedence-based parser for binary/ternary operators. /// /// Note: we diverge from the C99 grammar when parsing the assignment-expression @@ -282,7 +221,7 @@ ExprResult Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, - getLangOpts().CPlusPlus0x); + getLangOpts().CPlusPlus11); SourceLocation ColonLoc; while (1) { @@ -383,7 +322,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // they only appear on the RHS of assignments later. ExprResult RHS; bool RHSIsInitList = false; - if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { RHS = ParseBraceInitializer(); RHSIsInitList = true; } else if (getLangOpts().CPlusPlus && NextTokPrec <= prec::Conditional) @@ -398,7 +337,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // operator immediately to the right of the RHS. prec::Level ThisPrec = NextTokPrec; NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, - getLangOpts().CPlusPlus0x); + getLangOpts().CPlusPlus11); // Assignment and conditional expressions are right-associative. bool isRightAssoc = ThisPrec == prec::Conditional || @@ -426,7 +365,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { LHS = ExprError(); NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, - getLangOpts().CPlusPlus0x); + getLangOpts().CPlusPlus11); } assert(NextTokPrec <= ThisPrec && "Recursion didn't work!"); @@ -1036,7 +975,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::annot_typename: if (isStartOfObjCClassMessageMissingOpenBracket()) { ParsedType Type = getTypeAnnotation(Tok); - + // Fake up a Declarator to use with ActOnTypeName. DeclSpec DS(AttrFactory); DS.SetRangeStart(Tok.getLocation()); @@ -1046,7 +985,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, unsigned DiagID; DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(), PrevSpec, DiagID, Type); - + Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Ty.isInvalid()) @@ -1058,7 +997,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, break; } // Fall through - + case tok::annot_decltype: case tok::kw_char: case tok::kw_wchar_t: @@ -1078,7 +1017,15 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_void: case tok::kw_typename: case tok::kw_typeof: - case tok::kw___vector: { + case tok::kw___vector: + case tok::kw_image1d_t: + case tok::kw_image1d_array_t: + case tok::kw_image1d_buffer_t: + case tok::kw_image2d_t: + case tok::kw_image2d_array_t: + case tok::kw_image3d_t: + case tok::kw_sampler_t: + case tok::kw_event_t: { if (!getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_expression); return ExprError(); @@ -1097,7 +1044,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, DeclSpec DS(AttrFactory); ParseCXXSimpleTypeSpecifier(DS); if (Tok.isNot(tok::l_paren) && - (!getLangOpts().CPlusPlus0x || Tok.isNot(tok::l_brace))) + (!getLangOpts().CPlusPlus11 || Tok.isNot(tok::l_brace))) return ExprError(Diag(Tok, diag::err_expected_lparen_after_type) << DS.getSourceRange()); @@ -1241,10 +1188,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___is_union: case tok::kw___is_final: case tok::kw___has_trivial_constructor: + case tok::kw___has_trivial_move_constructor: case tok::kw___has_trivial_copy: case tok::kw___has_trivial_assign: + case tok::kw___has_trivial_move_assign: case tok::kw___has_trivial_destructor: case tok::kw___has_nothrow_assign: + case tok::kw___has_nothrow_move_assign: case tok::kw___has_nothrow_copy: case tok::kw___has_nothrow_constructor: case tok::kw___has_virtual_destructor: @@ -1282,7 +1232,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ExprError(); } case tok::l_square: - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { if (getLangOpts().ObjC1) { // C++11 lambda expressions and Objective-C message sends both start with a // square bracket. There are three possibilities here: @@ -1381,7 +1331,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { T.consumeOpen(); Loc = T.getOpenLocation(); ExprResult Idx; - if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); Idx = ParseBraceInitializer(); } else @@ -1459,7 +1409,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCall(getCurScope(), LHS.get(), - llvm::ArrayRef<Expr *>()); + ArrayRef<Expr *>()); cutOffParsing(); return ExprError(); } @@ -1663,11 +1613,11 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' -/// [C++0x] 'sizeof' '...' '(' identifier ')' +/// [C++11] 'sizeof' '...' '(' identifier ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' /// [C11] '_Alignof' '(' type-name ')' -/// [C++0x] 'alignof' '(' type-id ')' +/// [C++11] 'alignof' '(' type-id ')' /// \endverbatim ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) || @@ -1677,7 +1627,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { Token OpTok = Tok; ConsumeToken(); - // [C++0x] 'sizeof' '...' '(' identifier ')' + // [C++11] 'sizeof' '...' '(' identifier ')' if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) { SourceLocation EllipsisLoc = ConsumeToken(); SourceLocation LParenLoc, RParenLoc; @@ -1748,6 +1698,9 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { CastTy.getAsOpaquePtr(), CastRange); + if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) + Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo(); + // If we get here, the operand to the sizeof/alignof was an expresion. if (!Operand.isInvalid()) Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), @@ -2008,12 +1961,16 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, Tok.is(tok::kw___bridge_retained) || Tok.is(tok::kw___bridge_retain))); if (BridgeCast && !getLangOpts().ObjCAutoRefCount) { - StringRef BridgeCastName = Tok.getName(); - SourceLocation BridgeKeywordLoc = ConsumeToken(); - if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc)) - Diag(BridgeKeywordLoc, diag::warn_arc_bridge_cast_nonarc) - << BridgeCastName - << FixItHint::CreateReplacement(BridgeKeywordLoc, ""); + if (Tok.isNot(tok::kw___bridge)) { + StringRef BridgeCastName = Tok.getName(); + SourceLocation BridgeKeywordLoc = ConsumeToken(); + if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc)) + Diag(BridgeKeywordLoc, diag::warn_arc_bridge_cast_nonarc) + << BridgeCastName + << FixItHint::CreateReplacement(BridgeKeywordLoc, ""); + } + else + ConsumeToken(); // consume __bridge BridgeCast = false; } @@ -2360,10 +2317,10 @@ ExprResult Parser::ParseGenericSelectionExpression() { /// [C++0x] braced-init-list /// \endverbatim bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, - SmallVectorImpl<SourceLocation> &CommaLocs, - void (Sema::*Completer)(Scope *S, - Expr *Data, - llvm::ArrayRef<Expr *> Args), + SmallVectorImpl<SourceLocation> &CommaLocs, + void (Sema::*Completer)(Scope *S, + Expr *Data, + ArrayRef<Expr *> Args), Expr *Data) { while (1) { if (Tok.is(tok::code_completion)) { @@ -2376,7 +2333,7 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, } ExprResult Expr; - if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); Expr = ParseBraceInitializer(); } else diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 2f615e1..17c4adf 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Lex/LiteralSupport.h" +#include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -99,7 +99,7 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, /// \brief Emits an error for a left parentheses after a double colon. /// /// When a '(' is found after a '::', emit an error. Attempt to fix the token -/// stream by removing the '(', and the matching ')' if it found. +/// stream by removing the '(', and the matching ')' if found. void Parser::CheckForLParenAfterColonColon() { if (!Tok.is(tok::l_paren)) return; @@ -168,19 +168,26 @@ void Parser::CheckForLParenAfterColonColon() { /// if we do end up determining that we are parsing a destructor name, /// the last component of the nested-name-specifier is not parsed as /// part of the scope specifier. - -/// member access expression, e.g., the \p T:: in \p p->T::m. +/// +/// \param IsTypename If \c true, this nested-name-specifier is known to be +/// part of a type name. This is used to improve error recovery. +/// +/// \param LastII When non-NULL, points to an IdentifierInfo* that will be +/// filled in with the leading identifier in the last component of the +/// nested-name-specifier, if any. /// /// \returns true if there was an error parsing a scope specifier bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType, bool EnteringContext, bool *MayBePseudoDestructor, - bool IsTypename) { + bool IsTypename, + IdentifierInfo **LastII) { assert(getLangOpts().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); if (Tok.is(tok::annot_cxxscope)) { + assert(!LastII && "want last identifier but have already annotated scope"); Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); @@ -188,6 +195,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (LastII) + *LastII = 0; + bool HasScopeSpecifier = false; if (Tok.is(tok::coloncolon)) { @@ -334,6 +344,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (LastII) + *LastII = TemplateId->Name; + // Consume the template-id token. ConsumeToken(); @@ -405,6 +418,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (LastII) + *LastII = &II; + // We have an identifier followed by a '::'. Lookup this name // as the name in a nested-name-specifier. SourceLocation IdLoc = ConsumeToken(); @@ -602,7 +618,7 @@ ExprResult Parser::ParseLambdaExpression() { // Parse lambda-introducer. LambdaIntroducer Intro; - llvm::Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro)); + Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro)); if (DiagID) { Diag(Tok, DiagID.getValue()); SkipUntil(tok::r_square); @@ -620,7 +636,7 @@ ExprResult Parser::ParseLambdaExpression() { /// /// If we are not looking at a lambda expression, returns ExprError(). ExprResult Parser::TryParseLambdaExpression() { - assert(getLangOpts().CPlusPlus0x + assert(getLangOpts().CPlusPlus11 && Tok.is(tok::l_square) && "Not at the start of a possible lambda expression."); @@ -658,8 +674,8 @@ ExprResult Parser::TryParseLambdaExpression() { /// ParseLambdaExpression - Parse a lambda introducer. /// /// Returns a DiagnosticID if it hit something unexpected. -llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro){ - typedef llvm::Optional<unsigned> DiagResult; +Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) { + typedef Optional<unsigned> DiagResult; assert(Tok.is(tok::l_square) && "Lambda expressions begin with '['."); BalancedDelimiterTracker T(*this, tok::l_square); @@ -769,7 +785,7 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro){ bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) { TentativeParsingAction PA(*this); - llvm::Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro)); + Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro)); if (DiagID) { PA.Revert(); @@ -797,6 +813,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( if (Tok.is(tok::l_paren)) { ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | Scope::DeclScope); SourceLocation DeclEndLoc; @@ -806,7 +823,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // Parse parameter-declaration-clause. ParsedAttributes Attr(AttrFactory); - llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; + SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; SourceLocation EllipsisLoc; if (Tok.isNot(tok::r_paren)) @@ -826,8 +843,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // Parse exception-specification[opt]. ExceptionSpecificationType ESpecType = EST_None; SourceRange ESpecRange; - llvm::SmallVector<ParsedType, 2> DynamicExceptions; - llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges; + SmallVector<ParsedType, 2> DynamicExceptions; + SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; ESpecType = tryParseExceptionSpecification(ESpecRange, DynamicExceptions, @@ -838,7 +855,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DeclEndLoc = ESpecRange.getEnd(); // Parse attribute-specifier[opt]. - MaybeParseCXX0XAttributes(Attr, &DeclEndLoc); + MaybeParseCXX11Attributes(Attr, &DeclEndLoc); SourceLocation FunLocalRangeEnd = DeclEndLoc; @@ -1288,7 +1305,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); assert((Tok.is(tok::l_paren) || - (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace))) + (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))) && "Expected '(' or '{'!"); if (Tok.is(tok::l_brace)) { @@ -1362,7 +1379,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, } ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); if (!isCXXConditionDeclaration()) { ProhibitAttributes(attrs); @@ -1382,6 +1399,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, // type-specifier-seq DeclSpec DS(AttrFactory); + DS.takeAttributesFrom(attrs); ParseSpecifierQualifierList(DS); // declarator @@ -1416,7 +1434,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, ConsumeToken(); ExprResult InitExpr = ExprError(); - if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok.getLocation(), diag::warn_cxx98_compat_generalized_initializer_lists); InitExpr = ParseBraceInitializer(); @@ -1851,7 +1869,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, SymbolLocations[SymbolIdx++] = ConsumeToken(); // Check for array new/delete. if (Tok.is(tok::l_square) && - (!getLangOpts().CPlusPlus0x || NextToken().isNot(tok::l_square))) { + (!getLangOpts().CPlusPlus11 || NextToken().isNot(tok::l_square))) { // Consume the '[' and ']'. BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); @@ -1928,7 +1946,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // operator string-literal identifier // operator user-defined-string-literal - if (getLangOpts().CPlusPlus0x && isTokenStringLiteral()) { + if (getLangOpts().CPlusPlus11 && isTokenStringLiteral()) { Diag(Tok.getLocation(), diag::warn_cxx98_compat_literal_operator); SourceLocation DiagLoc; @@ -1936,8 +1954,8 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // We're past translation phase 6, so perform string literal concatenation // before checking for "". - llvm::SmallVector<Token, 4> Toks; - llvm::SmallVector<SourceLocation, 4> TokLocs; + SmallVector<Token, 4> Toks; + SmallVector<SourceLocation, 4> TokLocs; while (isTokenStringLiteral()) { if (!Tok.is(tok::string_literal) && !DiagId) { // C++11 [over.literal]p1: @@ -1986,7 +2004,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, if (DiagId) { // This isn't a valid literal-operator-id, but we think we know // what the user meant. Tell them what they should have written. - llvm::SmallString<32> Str; + SmallString<32> Str; Str += "\"\" "; Str += II->getName(); Diag(DiagLoc, DiagId) << FixItHint::CreateReplacement( @@ -2361,7 +2379,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { Initializer = Actions.ActOnParenListExpr(ConstructorLParen, ConstructorRParen, ConstructorArgs); - } else if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus0x) { + } else if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus11) { Diag(Tok.getLocation(), diag::warn_cxx98_compat_generalized_initializer_lists); Initializer = ParseBraceInitializer(); @@ -2405,7 +2423,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { // Attributes here appertain to the array type. C++11 [expr.new]p5. ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX0XAttributes(Attrs); + MaybeParseCXX11Attributes(Attrs); D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, @@ -2493,11 +2511,15 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { switch(kind) { default: llvm_unreachable("Not a known unary type trait."); case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; + case tok::kw___has_nothrow_move_assign: return UTT_HasNothrowMoveAssign; case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; + case tok::kw___has_trivial_move_assign: return UTT_HasTrivialMoveAssign; case tok::kw___has_trivial_constructor: return UTT_HasTrivialDefaultConstructor; + case tok::kw___has_trivial_move_constructor: + return UTT_HasTrivialMoveConstructor; case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; @@ -2659,7 +2681,7 @@ ExprResult Parser::ParseTypeTrait() { if (Parens.expectAndConsume(diag::err_expected_lparen)) return ExprError(); - llvm::SmallVector<ParsedType, 2> Args; + SmallVector<ParsedType, 2> Args; do { // Parse the next type. TypeResult Ty = ParseTypeName(); diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index e47fd9b..3b96717 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "clang/Parse/ParseDiagnostic.h" #include "RAIIObjectsForParser.h" +#include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/SmallString.h" @@ -33,7 +33,7 @@ bool Parser::MayBeDesignationStart() { return true; case tok::l_square: { // designator: array-designator - if (!PP.getLangOpts().CPlusPlus0x) + if (!PP.getLangOpts().CPlusPlus11) return true; // C++11 lambda expressions and C99 designators can be ambiguous all the diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index d321baf..ad95dd5 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" @@ -21,6 +22,18 @@ #include "llvm/ADT/StringExtras.h" using namespace clang; +/// Skips attributes after an Objective-C @ directive. Emits a diagnostic. +void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) { + ParsedAttributes attrs(AttrFactory); + if (Tok.is(tok::kw___attribute)) { + if (Kind == tok::objc_interface || Kind == tok::objc_protocol) + Diag(Tok, diag::err_objc_postfix_attribute_hint) + << (Kind == tok::objc_protocol); + else + Diag(Tok, diag::err_objc_postfix_attribute); + ParseGNUAttributes(attrs); + } +} /// ParseObjCAtDirectives - Handle parts of the external-declaration production: /// external-declaration: [C99 6.9] @@ -65,7 +78,7 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { case tok::objc_dynamic: SingleDecl = ParseObjCPropertyDynamic(AtLoc); break; - case tok::objc___experimental_modules_import: + case tok::objc_import: if (getLangOpts().Modules) return ParseModuleImport(AtLoc); @@ -92,6 +105,7 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { while (1) { + MaybeSkipAttributes(tok::objc_class); if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); SkipUntil(tok::semi); @@ -178,6 +192,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, return 0; } + MaybeSkipAttributes(tok::objc_interface); + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing class or category name. return 0; @@ -690,7 +706,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { case tok::caret: case tok::caretequal: { std::string ThisTok(PP.getSpelling(Tok)); - if (isalpha(ThisTok[0])) { + if (isLetter(ThisTok[0])) { IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok.data()); Tok.setKind(tok::identifier); SelectorLoc = ConsumeToken(); @@ -1028,8 +1044,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, SmallVector<IdentifierInfo *, 12> KeyIdents; SmallVector<SourceLocation, 12> KeyLocs; SmallVector<Sema::ObjCArgInfo, 12> ArgInfos; - ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); + ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | Scope::DeclScope); AttributePool allParamAttrs(AttrFactory); while (1) { @@ -1200,12 +1216,8 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, } // Consume the '>'. - if (Tok.isNot(tok::greater)) { - Diag(Tok, diag::err_expected_greater); + if (ParseGreaterThanInTemplateList(EndLoc, /*ConsumeLastToken=*/true)) return true; - } - - EndLoc = ConsumeToken(); // Convert the list of protocols identifiers into a list of protocol decls. Actions.FindProtocolDeclaration(WarnOnDeclarations, @@ -1231,6 +1243,22 @@ bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) { return Result; } +void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc, + BalancedDelimiterTracker &T, + SmallVectorImpl<Decl *> &AllIvarDecls, + bool RBraceMissing) { + if (!RBraceMissing) + T.consumeClose(); + + Actions.ActOnObjCContainerStartDefinition(interfaceDecl); + Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls); + Actions.ActOnObjCContainerFinishDefinition(); + // Call ActOnFields() even if we don't have any decls. This is useful + // for code rewriting tools that need to be aware of the empty list. + Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, + AllIvarDecls, + T.getOpenLocation(), T.getCloseLocation(), 0); +} /// objc-class-instance-variables: /// '{' objc-instance-variable-decl-list[opt] '}' @@ -1263,7 +1291,6 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); - // While we still have something to read, read the instance variables. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // Each iteration of this loop reads one objc-instance-variable-decl. @@ -1291,6 +1318,17 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, visibility = Tok.getObjCKeywordID(); ConsumeToken(); continue; + + case tok::objc_end: + Diag(Tok, diag::err_objc_unexpected_atend); + Tok.setLocation(Tok.getLocation().getLocWithOffset(-1)); + Tok.setKind(tok::at); + Tok.setLength(1); + PP.EnterToken(Tok); + HelperActionsForIvarDeclarations(interfaceDecl, atLoc, + T, AllIvarDecls, true); + return; + default: Diag(Tok, diag::err_objc_illegal_visibility_spec); continue; @@ -1340,16 +1378,8 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, SkipUntil(tok::r_brace, true, true); } } - T.consumeClose(); - - Actions.ActOnObjCContainerStartDefinition(interfaceDecl); - Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls); - Actions.ActOnObjCContainerFinishDefinition(); - // Call ActOnFields() even if we don't have any decls. This is useful - // for code rewriting tools that need to be aware of the empty list. - Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, - AllIvarDecls, - T.getOpenLocation(), T.getCloseLocation(), 0); + HelperActionsForIvarDeclarations(interfaceDecl, atLoc, + T, AllIvarDecls, false); return; } @@ -1382,6 +1412,8 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, return DeclGroupPtrTy(); } + MaybeSkipAttributes(tok::objc_protocol); + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing protocol name. return DeclGroupPtrTy(); @@ -1473,6 +1505,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { return DeclGroupPtrTy(); } + MaybeSkipAttributes(tok::objc_implementation); + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing class or category name. return DeclGroupPtrTy(); @@ -1540,7 +1574,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl); while (!ObjCImplParsing.isFinished() && Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) { DeclGroupRef DG = DGP.get(); @@ -2040,7 +2074,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Actions.MakeFullExpr(Res.take())); + return Actions.ActOnExprStmt(Res); } ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { @@ -2423,7 +2457,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, // Parse objc-selector SourceLocation Loc; IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc); - + SmallVector<IdentifierInfo *, 12> KeyIdents; SmallVector<SourceLocation, 12> KeyLocs; ExprVector KeyExprs; @@ -2547,7 +2581,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, SkipUntil(tok::r_square); return ExprError(); } - + SourceLocation RBracLoc = ConsumeBracket(); // consume ']' unsigned nKeys = KeyIdents.size(); @@ -2593,8 +2627,8 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { AtStrings.push_back(Lit.release()); } - return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(), - AtStrings.size())); + return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(), + AtStrings.size()); } /// ParseObjCBooleanLiteral - @@ -2617,7 +2651,7 @@ ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { return Lit; } ConsumeToken(); // Consume the literal token. - return Owned(Actions.BuildObjCNumericLiteral(AtLoc, Lit.take())); + return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()); } /// ParseObjCNumericLiteral - @@ -2631,7 +2665,7 @@ ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { return Lit; } ConsumeToken(); // Consume the literal token. - return Owned(Actions.BuildObjCNumericLiteral(AtLoc, Lit.take())); + return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()); } /// ParseObjCBoxedExpr - @@ -2655,8 +2689,8 @@ Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { // a boxed expression from a literal. SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation(); ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.take()); - return Owned(Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), - ValueExpr.take())); + return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), + ValueExpr.take()); } ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { @@ -2689,7 +2723,7 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { } SourceLocation EndLoc = ConsumeBracket(); // location of ']' MultiExprArg Args(ElementExprs); - return Owned(Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args)); + return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args); } ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { @@ -2733,7 +2767,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { // We have a valid expression. Collect it in a vector so we can // build the argument list. ObjCDictionaryElement Element = { - KeyExpr.get(), ValueExpr.get(), EllipsisLoc, llvm::Optional<unsigned>() + KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None }; Elements.push_back(Element); @@ -2745,9 +2779,8 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { SourceLocation EndLoc = ConsumeBrace(); // Create the ObjCDictionaryLiteral. - return Owned(Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), - Elements.data(), - Elements.size())); + return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), + Elements.data(), Elements.size()); } /// objc-encode-expression: @@ -2771,9 +2804,8 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { if (Ty.isInvalid()) return ExprError(); - return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, - T.getOpenLocation(), Ty.get(), - T.getCloseLocation())); + return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, T.getOpenLocation(), + Ty.get(), T.getCloseLocation()); } /// objc-protocol-expression @@ -2796,10 +2828,9 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { T.consumeClose(); - return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, - T.getOpenLocation(), - ProtoIdLoc, - T.getCloseLocation())); + return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, + T.getOpenLocation(), ProtoIdLoc, + T.getCloseLocation()); } /// objc-selector-expression @@ -2860,9 +2891,9 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { } T.consumeClose(); Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]); - return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, - T.getOpenLocation(), - T.getCloseLocation())); + return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, + T.getOpenLocation(), + T.getCloseLocation()); } void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { @@ -2884,7 +2915,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); // Consume the previously pushed token. - ConsumeAnyToken(); + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || Tok.is(tok::colon)) && diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp new file mode 100644 index 0000000..507a6b1 --- /dev/null +++ b/lib/Parse/ParseOpenMP.cpp @@ -0,0 +1,118 @@ +//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// \brief This file implements parsing of all OpenMP directives and clauses. +/// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTConsumer.h" +#include "clang/Parse/Parser.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "RAIIObjectsForParser.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +// OpenMP declarative directives. +//===----------------------------------------------------------------------===// + +/// \brief Parses OpenMP declarative directive +/// threadprivate-directive +/// annot_pragma_openmp threadprivate simple-variable-list +/// +Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { + assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); + + SourceLocation Loc = ConsumeToken(); + SmallVector<DeclarationNameInfo, 5> Identifiers; + OpenMPDirectiveKind Kind = Tok.isAnnotation() ? + OMPD_unknown : + getOpenMPDirectiveKind(PP.getSpelling(Tok)); + switch(Kind) { + case OMPD_threadprivate: + ConsumeToken(); + if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers)) { + // The last seen token is annot_pragma_openmp_end - need to check for + // extra tokens. + if (Tok.isNot(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::warn_omp_extra_tokens_at_eol) + << getOpenMPDirectiveName(OMPD_threadprivate); + SkipUntil(tok::annot_pragma_openmp_end, false, true); + } + ConsumeToken(); + return Actions.ActOnOpenMPThreadprivateDirective(Loc, + getCurScope(), + Identifiers); + } + break; + case OMPD_unknown: + Diag(Tok, diag::err_omp_unknown_directive); + break; + default: + Diag(Tok, diag::err_omp_unexpected_directive) + << getOpenMPDirectiveName(Kind); + break; + } + SkipUntil(tok::annot_pragma_openmp_end, false); + return DeclGroupPtrTy(); +} + +/// \brief Parses list of simple variables for '#pragma omp threadprivate' +/// directive +/// simple-variable-list: +/// ( unqualified-id {, unqualified-id} ) annot_pragma_openmp_end +/// +bool Parser::ParseOpenMPSimpleVarList( + OpenMPDirectiveKind Kind, + SmallVectorImpl<DeclarationNameInfo> &IdList) { + // Parse '('. + bool IsCorrect = true; + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPDirectiveName(Kind))) { + SkipUntil(tok::annot_pragma_openmp_end, false, true); + return false; + } + + // Read tokens while ')' or annot_pragma_openmp_end is not found. + do { + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + // Read var name. + Token PrevTok = Tok; + + if (ParseUnqualifiedId(SS, false, false, false, ParsedType(), + TemplateKWLoc, Name)) { + IsCorrect = false; + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + false, true); + } + else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && + Tok.isNot(tok::annot_pragma_openmp_end)) { + IsCorrect = false; + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + false, true); + Diag(PrevTok.getLocation(), diag::err_expected_unqualified_id) + << getLangOpts().CPlusPlus + << SourceRange(PrevTok.getLocation(), PrevTokLocation); + } else { + IdList.push_back(Actions.GetNameFromUnqualifiedId(Name)); + } + // Consume ','. + if (Tok.is(tok::comma)) { + ConsumeToken(); + } + } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)); + + if (IsCorrect || Tok.is(tok::r_paren)) { + IsCorrect = !T.consumeClose() && IsCorrect; + } + + return !IsCorrect && IdList.empty(); +} diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index a7605f0..dc6b3ed 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "ParsePragma.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" -#include "clang/Lex/Preprocessor.h" using namespace clang; /// \brief Handle the annotation token produced for #pragma unused(...) @@ -718,3 +718,47 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, /*OwnsTokens=*/false); } +/// \brief Handle '#pragma omp ...' when OpenMP is disabled. +/// +void +PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &FirstTok) { + if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored, + FirstTok.getLocation()) != + DiagnosticsEngine::Ignored) { + PP.Diag(FirstTok, diag::warn_pragma_omp_ignored); + PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored, + diag::MAP_IGNORE, + SourceLocation()); + } + PP.DiscardUntilEndOfDirective(); +} + +/// \brief Handle '#pragma omp ...' when OpenMP is enabled. +/// +void +PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &FirstTok) { + SmallVector<Token, 16> Pragma; + Token Tok; + Tok.startToken(); + Tok.setKind(tok::annot_pragma_openmp); + Tok.setLocation(FirstTok.getLocation()); + + while (Tok.isNot(tok::eod)) { + Pragma.push_back(Tok); + PP.Lex(Tok); + } + SourceLocation EodLoc = Tok.getLocation(); + Tok.startToken(); + Tok.setKind(tok::annot_pragma_openmp_end); + Tok.setLocation(EodLoc); + Pragma.push_back(Tok); + + Token *Toks = new Token[Pragma.size()]; + std::copy(Pragma.begin(), Pragma.end(), Toks); + PP.EnterTokenStream(Toks, Pragma.size(), + /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); +} diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h index b9a2a25..841a60b 100644 --- a/lib/Parse/ParsePragma.h +++ b/lib/Parse/ParsePragma.h @@ -98,7 +98,20 @@ public: virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; - + +class PragmaNoOpenMPHandler : public PragmaHandler { +public: + PragmaNoOpenMPHandler() : PragmaHandler("omp") { } + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); +}; + +class PragmaOpenMPHandler : public PragmaHandler { +public: + PragmaOpenMPHandler() : PragmaHandler("omp") { } + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); +}; } // end namespace clang diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 5883115..355f369 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -14,13 +14,13 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/SourceManager.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/PrettyStackTrace.h" -#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -84,7 +84,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, ParenBraceBracketBalancer BalancerRAIIObj(*this); ParsedAttributesWithRange Attrs(AttrFactory); - MaybeParseCXX0XAttributes(Attrs, 0, /*MightBeObjCMessageSend*/ true); + MaybeParseCXX11Attributes(Attrs, 0, /*MightBeObjCMessageSend*/ true); StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts, OnlyStatement, TrailingElseLoc, Attrs); @@ -288,6 +288,11 @@ Retry: ProhibitAttributes(Attrs); HandlePragmaOpenCLExtension(); return StmtEmpty(); + + case tok::annot_pragma_openmp: + SourceLocation DeclStart = Tok.getLocation(); + DeclGroupPtrTy Res = ParseOpenMPDeclarativeDirective(); + return Actions.ActOnDeclStmt(Res, DeclStart, Tok.getLocation()); } // If we reached this code, the statement must end in a semicolon. @@ -319,7 +324,7 @@ StmtResult Parser::ParseExprStatement() { SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); if (Tok.is(tok::semi)) ConsumeToken(); - return StmtError(); + return Actions.ActOnExprStmtError(); } if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() && @@ -335,7 +340,7 @@ StmtResult Parser::ParseExprStatement() { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get())); + return Actions.ActOnExprStmt(Expr); } StmtResult Parser::ParseSEHTryBlock() { @@ -830,7 +835,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ConsumeToken(); ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs, 0, /*MightBeObjCMessageSend*/ true); + MaybeParseCXX11Attributes(attrs, 0, /*MightBeObjCMessageSend*/ true); // If this is the start of a declaration, parse it as such. if (isDeclarationStatement()) { @@ -856,7 +861,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // Eat the semicolon at the end of stmt and convert the expr into a // statement. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res.get())); + R = Actions.ActOnExprStmt(Res); } } @@ -867,15 +872,10 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { SourceLocation CloseLoc = Tok.getLocation(); // We broke out of the while loop because we found a '}' or EOF. - if (Tok.isNot(tok::r_brace)) { - Diag(Tok, diag::err_expected_rbrace); - Diag(T.getOpenLocation(), diag::note_matching) << "{"; + if (!T.consumeClose()) // Recover by creating a compound statement with what we parsed so far, // instead of dropping everything and returning StmtError(); - } else { - if (!T.consumeClose()) - CloseLoc = T.getCloseLocation(); - } + CloseLoc = T.getCloseLocation(); return Actions.ActOnCompoundStmt(T.getOpenLocation(), CloseLoc, Stmts, isStmtExpr); @@ -1047,11 +1047,6 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { IfScope.Exit(); - // If the condition was invalid, discard the if statement. We could recover - // better by replacing it with a valid expr, but don't do that yet. - if (CondExp.isInvalid() && !CondVar) - return StmtError(); - // If the then or else stmt is invalid and the other is valid (and present), // make turn the invalid one into a null stmt to avoid dropping the other // part. If both are invalid, return error. @@ -1290,7 +1285,7 @@ StmtResult Parser::ParseDoStatement() { // FIXME: Do not just parse the attribute contents and throw them away ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); ProhibitAttributes(attrs); ExprResult Cond = ParseExpression(); @@ -1383,7 +1378,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { } ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); // Parse the first part of the for specifier. if (Tok.is(tok::semi)) { // for (; @@ -1395,9 +1390,6 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); - ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); - // In C++0x, "for (T NS:a" might not be a typo for :: bool MightBeForRangeStmt = getLangOpts().CPlusPlus; ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); @@ -1411,7 +1403,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (ForRangeInit.ParsedForRangeDecl()) { - Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus0x ? + Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_for_range : diag::ext_for_range); ForRange = true; @@ -1442,7 +1434,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (ForEach) FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); else - FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value.get())); + FirstPart = Actions.ActOnExprStmt(Value); } if (Tok.is(tok::semi)) { @@ -1456,7 +1448,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); } Collection = ParseExpression(); - } else if (getLangOpts().CPlusPlus0x && Tok.is(tok::colon) && FirstPart.get()) { + } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::colon) && FirstPart.get()) { // User tried to write the reasonable, but ill-formed, for-range-statement // for (expr : expr) { ... } Diag(Tok, diag::err_for_range_expected_decl) @@ -1510,7 +1502,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Parse the third part of the for specifier. if (Tok.isNot(tok::r_paren)) { // for (...;...;) ExprResult Third = ParseExpression(); - ThirdPart = Actions.MakeFullExpr(Third.take()); + // FIXME: The C++11 standard doesn't actually say that this is a + // discarded-value expression, but it clearly should be. + ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.take()); } } // Match the ')'. @@ -1652,7 +1646,7 @@ StmtResult Parser::ParseReturnStatement() { if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus) { R = ParseInitializer(); if (R.isUsable()) - Diag(R.get()->getLocStart(), getLangOpts().CPlusPlus0x ? + Diag(R.get()->getLocStart(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_generalized_initializer_lists : diag::ext_generalized_initializer_lists) << R.get()->getSourceRange(); @@ -1682,9 +1676,6 @@ StmtResult Parser::ParseReturnStatement() { /// ms-asm-line '\n' ms-asm-instruction-block /// StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { - // MS-style inline assembly is not fully supported, so emit a warning. - Diag(AsmLoc, diag::warn_unsupported_msasm); - SourceManager &SrcMgr = PP.getSourceManager(); SourceLocation EndLoc = AsmLoc; SmallVector<Token, 4> AsmToks; @@ -1777,21 +1768,6 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { return StmtError(); } - // If MS-style inline assembly is disabled, then build an empty asm. - if (!getLangOpts().EmitMicrosoftInlineAsm) { - Token t; - t.setKind(tok::string_literal); - t.setLiteralData("\"/*FIXME: not done*/\""); - t.clearFlag(Token::NeedsCleaning); - t.setLength(21); - ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1)); - ExprVector Constraints; - ExprVector Exprs; - ExprVector Clobbers; - return Actions.ActOnGCCAsmStmt(AsmLoc, true, true, 0, 0, 0, Constraints, - Exprs, AsmString.take(), Clobbers, EndLoc); - } - // FIXME: We should be passing source locations for better diagnostics. return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, llvm::makeArrayRef(AsmToks), EndLoc); @@ -1820,7 +1796,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); - if (getLangOpts().MicrosoftExt && Tok.isNot(tok::l_paren) && + if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { msAsm = true; return ParseMicrosoftAsmStatement(AsmLoc); @@ -1834,6 +1810,9 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { Diag(Loc, diag::w_asm_qualifier_ignored) << "const"; if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict"; + // FIXME: Once GCC supports _Atomic, check whether it permits it here. + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) + Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic"; // Remember if this was a volatile asm. bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; @@ -2003,9 +1982,10 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - if (SkipFunctionBodies && trySkippingFunctionBody()) { + if (SkipFunctionBodies && (!Decl || Actions.canSkipFunctionBody(Decl)) && + trySkippingFunctionBody()) { BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(Decl, 0); + return Actions.ActOnSkippedFunctionBody(Decl); } PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, @@ -2045,9 +2025,10 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { else Actions.ActOnDefaultCtorInitializers(Decl); - if (SkipFunctionBodies && trySkippingFunctionBody()) { + if (SkipFunctionBodies && Actions.canSkipFunctionBody(Decl) && + trySkippingFunctionBody()) { BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(Decl, 0); + return Actions.ActOnSkippedFunctionBody(Decl); } SourceLocation LBraceLoc = Tok.getLocation(); @@ -2123,8 +2104,8 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { // FIXME: Possible draft standard bug: attribute-specifier should be allowed? StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, - Scope::DeclScope | - (FnTry ? Scope::FnTryScope : Scope::TryScope))); + Scope::DeclScope | Scope::TryScope | + (FnTry ? Scope::FnTryCatchScope : 0))); if (TryBlock.isInvalid()) return TryBlock; @@ -2154,7 +2135,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { else { StmtVector Handlers; ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); ProhibitAttributes(attrs); if (Tok.isNot(tok::kw_catch)) @@ -2175,14 +2156,13 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard /// -/// handler: -/// 'catch' '(' exception-declaration ')' compound-statement +/// handler: +/// 'catch' '(' exception-declaration ')' compound-statement /// -/// exception-declaration: -/// type-specifier-seq declarator -/// type-specifier-seq abstract-declarator -/// type-specifier-seq -/// '...' +/// exception-declaration: +/// attribute-specifier-seq[opt] type-specifier-seq declarator +/// attribute-specifier-seq[opt] type-specifier-seq abstract-declarator[opt] +/// '...' /// StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { assert(Tok.is(tok::kw_catch) && "Expected 'catch'"); @@ -2197,15 +2177,21 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { // The name in a catch exception-declaration is local to the handler and // shall not be redeclared in the outermost block of the handler. ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope | - (FnCatch ? Scope::FnCatchScope : Scope::CatchScope)); + (FnCatch ? Scope::FnTryCatchScope : 0)); // exception-declaration is equivalent to '...' or a parameter-declaration // without default arguments. Decl *ExceptionDecl = 0; if (Tok.isNot(tok::ellipsis)) { + ParsedAttributesWithRange Attributes(AttrFactory); + MaybeParseCXX11Attributes(Attributes); + DeclSpec DS(AttrFactory); + DS.takeAttributesFrom(Attributes); + if (ParseCXXTypeSpecifierSeq(DS)) return StmtError(); + Declarator ExDecl(DS, Declarator::CXXCatchContext); ParseDeclarator(ExDecl); ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl); diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 2e0411e..f146669 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -12,13 +12,13 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" +#include "RAIIObjectsForParser.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" -#include "RAIIObjectsForParser.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/ASTConsumer.h" using namespace clang; /// \brief Parse a template declaration, explicit instantiation, or @@ -172,16 +172,6 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, /// \brief Parse a single declaration that declares a template, /// template specialization, or explicit instantiation of a template. /// -/// \param TemplateParams if non-NULL, the template parameter lists -/// that preceded this declaration. In this case, the declaration is a -/// template declaration, out-of-line definition of a template, or an -/// explicit template specialization. When NULL, the declaration is an -/// explicit template instantiation. -/// -/// \param TemplateLoc when TemplateParams is NULL, the location of -/// the 'template' keyword that indicates that we have an explicit -/// template instantiation. -/// /// \param DeclEnd will receive the source location of the last token /// within this declaration. /// @@ -208,7 +198,7 @@ Parser::ParseSingleDeclarationAfterTemplate( } ParsedAttributesWithRange prefixAttrs(AttrFactory); - MaybeParseCXX0XAttributes(prefixAttrs); + MaybeParseCXX11Attributes(prefixAttrs); if (Tok.is(tok::kw_using)) return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd, @@ -218,22 +208,27 @@ Parser::ParseSingleDeclarationAfterTemplate( // the template parameters. ParsingDeclSpec DS(*this, &DiagsFromTParams); - // Move the attributes from the prefix into the DS. - if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) - ProhibitAttributes(prefixAttrs); - else - DS.takeAttributesFrom(prefixAttrs); - ParseDeclarationSpecifiers(DS, TemplateInfo, AS, getDeclSpecContextFromDeclaratorContext(Context)); if (Tok.is(tok::semi)) { + ProhibitAttributes(prefixAttrs); DeclEnd = ConsumeToken(); - Decl *Decl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); + Decl *Decl = Actions.ParsedFreeStandingDeclSpec( + getCurScope(), AS, DS, + TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams + : MultiTemplateParamsArg(), + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation); DS.complete(Decl); return Decl; } + // Move the attributes from the prefix into the DS. + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) + ProhibitAttributes(prefixAttrs); + else + DS.takeAttributesFrom(prefixAttrs); + // Parse the declarator. ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context); ParseDeclarator(DeclaratorInfo); @@ -250,27 +245,6 @@ Parser::ParseSingleDeclarationAfterTemplate( if (DeclaratorInfo.isFunctionDeclarator()) MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); - // If we have a declaration or declarator list, handle it. - if (isDeclarationAfterDeclarator()) { - // Parse this declaration. - Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, - TemplateInfo); - - if (Tok.is(tok::comma)) { - Diag(Tok, diag::err_multiple_template_declarators) - << (int)TemplateInfo.Kind; - SkipUntil(tok::semi, true, false); - return ThisDecl; - } - - // Eat the semi colon after the declaration. - ExpectAndConsumeSemi(diag::err_expected_semi_declaration); - if (LateParsedAttrs.size() > 0) - ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false); - DeclaratorInfo.complete(ThisDecl); - return ThisDecl; - } - if (DeclaratorInfo.isFunctionDeclarator() && isStartOfFunctionDefinition(DeclaratorInfo)) { if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -285,12 +259,23 @@ Parser::ParseSingleDeclarationAfterTemplate( &LateParsedAttrs); } - if (DeclaratorInfo.isFunctionDeclarator()) - Diag(Tok, diag::err_expected_fn_body); - else - Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); - SkipUntil(tok::semi); - return 0; + // Parse this declaration. + Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, + TemplateInfo); + + if (Tok.is(tok::comma)) { + Diag(Tok, diag::err_multiple_template_declarators) + << (int)TemplateInfo.Kind; + SkipUntil(tok::semi, true, false); + return ThisDecl; + } + + // Eat the semi colon after the declaration. + ExpectAndConsumeSemi(diag::err_expected_semi_declaration); + if (LateParsedAttrs.size() > 0) + ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false); + DeclaratorInfo.complete(ThisDecl); + return ThisDecl; } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in @@ -357,7 +342,7 @@ Parser::ParseTemplateParameterList(unsigned Depth, SkipUntil(tok::comma, tok::greater, tok::greatergreater, true, true); } - // Did we find a comma or the end of the template parmeter list? + // Did we find a comma or the end of the template parameter list? if (Tok.is(tok::comma)) { ConsumeToken(); } else if (Tok.is(tok::greater) || Tok.is(tok::greatergreater)) { @@ -491,7 +476,7 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { EllipsisLoc = ConsumeToken(); Diag(EllipsisLoc, - getLangOpts().CPlusPlus0x + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates : diag::ext_variadic_templates); } @@ -578,7 +563,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { EllipsisLoc = ConsumeToken(); Diag(EllipsisLoc, - getLangOpts().CPlusPlus0x + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates : diag::ext_variadic_templates); } @@ -675,52 +660,17 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { DefaultArg.take()); } -/// \brief Parses a template-id that after the template name has -/// already been parsed. -/// -/// This routine takes care of parsing the enclosed template argument -/// list ('<' template-parameter-list [opt] '>') and placing the -/// results into a form that can be transferred to semantic analysis. +/// \brief Parses a '>' at the end of a template list. /// -/// \param Template the template declaration produced by isTemplateName -/// -/// \param TemplateNameLoc the source location of the template name +/// If this function encounters '>>', '>>>', '>=', or '>>=', it tries +/// to determine if these tokens were supposed to be a '>' followed by +/// '>', '>>', '>=', or '>='. It emits an appropriate diagnostic if necessary. /// -/// \param SS if non-NULL, the nested-name-specifier preceding the -/// template name. +/// \param RAngleLoc the location of the consumed '>'. /// -/// \param ConsumeLastToken if true, then we will consume the last -/// token that forms the template-id. Otherwise, we will leave the -/// last token in the stream (e.g., so that it can be replaced with an -/// annotation token). -bool -Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, - SourceLocation TemplateNameLoc, - const CXXScopeSpec &SS, - bool ConsumeLastToken, - SourceLocation &LAngleLoc, - TemplateArgList &TemplateArgs, - SourceLocation &RAngleLoc) { - assert(Tok.is(tok::less) && "Must have already parsed the template-name"); - - // Consume the '<'. - LAngleLoc = ConsumeToken(); - - // Parse the optional template-argument-list. - bool Invalid = false; - { - GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); - if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) - Invalid = ParseTemplateArgumentList(TemplateArgs); - - if (Invalid) { - // Try to find the closing '>'. - SkipUntil(tok::greater, true, !ConsumeLastToken); - - return true; - } - } - +/// \param ConsumeLastToken if true, the '>' is not consumed. +bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, + bool ConsumeLastToken) { // What will be left once we've consumed the '>'. tok::TokenKind RemainingToken; const char *ReplacementStr = "> >"; @@ -788,7 +738,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " "); unsigned DiagId = diag::err_two_right_angle_brackets_need_space; - if (getLangOpts().CPlusPlus0x && Tok.is(tok::greatergreater)) + if (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)) DiagId = diag::warn_cxx98_compat_two_right_angle_brackets; else if (Tok.is(tok::greaterequal)) DiagId = diag::err_right_angle_bracket_equal_needs_space; @@ -819,10 +769,59 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, Tok.setLength(1); Tok.setLocation(RAngleLoc); } - return false; } + +/// \brief Parses a template-id that after the template name has +/// already been parsed. +/// +/// This routine takes care of parsing the enclosed template argument +/// list ('<' template-parameter-list [opt] '>') and placing the +/// results into a form that can be transferred to semantic analysis. +/// +/// \param Template the template declaration produced by isTemplateName +/// +/// \param TemplateNameLoc the source location of the template name +/// +/// \param SS if non-NULL, the nested-name-specifier preceding the +/// template name. +/// +/// \param ConsumeLastToken if true, then we will consume the last +/// token that forms the template-id. Otherwise, we will leave the +/// last token in the stream (e.g., so that it can be replaced with an +/// annotation token). +bool +Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, + SourceLocation TemplateNameLoc, + const CXXScopeSpec &SS, + bool ConsumeLastToken, + SourceLocation &LAngleLoc, + TemplateArgList &TemplateArgs, + SourceLocation &RAngleLoc) { + assert(Tok.is(tok::less) && "Must have already parsed the template-name"); + + // Consume the '<'. + LAngleLoc = ConsumeToken(); + + // Parse the optional template-argument-list. + bool Invalid = false; + { + GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); + if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) + Invalid = ParseTemplateArgumentList(TemplateArgs); + + if (Invalid) { + // Try to find the closing '>'. + SkipUntil(tok::greater, true, !ConsumeLastToken); + + return true; + } + } + + return ParseGreaterThanInTemplateList(RAngleLoc, ConsumeLastToken); +} + /// \brief Replace the tokens that form a simple-template-id with an /// annotation token containing the complete template-id. /// @@ -839,7 +838,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, /// \param Template the declaration of the template named by the first /// token (an identifier), as returned from \c Action::isTemplateName(). /// -/// \param TemplateNameKind the kind of template that \p Template +/// \param TNK the kind of template that \p Template /// refers to, as returned from \c Action::isTemplateName(). /// /// \param SS if non-NULL, the nested-name-specifier that precedes @@ -1201,7 +1200,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { /// explicit-instantiation: /// 'extern' [opt] 'template' declaration /// -/// Note that the 'extern' is a GNU extension and C++0x feature. +/// Note that the 'extern' is a GNU extension and C++11 feature. Decl *Parser::ParseExplicitInstantiation(unsigned Context, SourceLocation ExternLoc, SourceLocation TemplateLoc, @@ -1306,7 +1305,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false); // Consume the previously pushed token. - ConsumeAnyToken(); + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && "Inline method not starting with '{', ':' or 'try'"); diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 40c4eee..5e0ef2b 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -184,6 +184,9 @@ Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) { return TPResult::Ambiguous(); } +/// Tentatively parse an init-declarator-list in order to disambiguate it from +/// an expression. +/// /// init-declarator-list: /// init-declarator /// init-declarator-list ',' init-declarator @@ -192,14 +195,21 @@ Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) { /// declarator initializer[opt] /// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt] /// -/// initializer: -/// '=' initializer-clause -/// '(' expression-list ')' +/// 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 /// -/// initializer-clause: -/// assignment-expression -/// '{' initializer-list ','[opt] '}' -/// '{' '}' +/// braced-init-list: +/// '{' initializer-list ','[opt] '}' +/// '{' '}' /// Parser::TPResult Parser::TryParseInitDeclaratorList() { while (1) { @@ -218,6 +228,10 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() { ConsumeParen(); if (!SkipUntil(tok::r_paren)) return TPResult::Error(); + } else if (Tok.is(tok::l_brace)) { + // A left-brace here is sufficient to disambiguate the parse; an + // expression can never be followed directly by a braced-init-list. + return TPResult::True(); } else if (Tok.is(tok::equal) || isTokIdentifier_in()) { // MSVC and g++ won't examine the rest of declarators if '=' is // encountered; they just conclude that we have a declaration. @@ -295,7 +309,7 @@ bool Parser::isCXXConditionDeclaration() { if (Tok.is(tok::equal) || Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) TPR = TPResult::True(); - else if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) + else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) TPR = TPResult::True(); else TPR = TPResult::False(); @@ -379,7 +393,7 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { // ',', this is a type-id. Otherwise, it's an expression. } else if (Context == TypeIdAsTemplateArgument && (Tok.is(tok::greater) || Tok.is(tok::comma) || - (getLangOpts().CPlusPlus0x && Tok.is(tok::greatergreater)))) { + (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) { TPR = TPResult::True(); isAmbiguous = true; @@ -837,6 +851,15 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___vector: case tok::kw___pixel: case tok::kw__Atomic: + case tok::kw_image1d_t: + case tok::kw_image1d_array_t: + case tok::kw_image1d_buffer_t: + case tok::kw_image2d_t: + case tok::kw_image2d_array_t: + case tok::kw_image3d_t: + case tok::kw_sampler_t: + case tok::kw_event_t: + case tok::kw___unknown_anytype: return TPResult::False(); default: @@ -976,6 +999,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // to types and identifiers, in order to try to recover from errors. CorrectionCandidateCallback TypoCorrection; TypoCorrection.WantRemainingKeywords = false; + TypoCorrection.WantTypeSpecifiers = Next.isNot(tok::arrow); switch (TryAnnotateName(false /* no nested name specifier */, &TypoCorrection)) { case ANK_Error: @@ -1056,6 +1080,9 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // Modules case tok::kw___module_private__: + + // Debugger support + case tok::kw___unknown_anytype: // type-specifier: // simple-type-specifier @@ -1212,7 +1239,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, if (isFollowedByParen) return TPResult::Ambiguous(); - if (getLangOpts().CPlusPlus0x && isFollowedByBrace) + if (getLangOpts().CPlusPlus11 && isFollowedByBrace) return BracedCastResult; return TPResult::True(); @@ -1244,7 +1271,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // enum E : int { a = 4 }; // enum // enum E : int { 4 }; // bit-field // }; - if (getLangOpts().CPlusPlus0x && NextToken().is(tok::l_brace)) + if (getLangOpts().CPlusPlus11 && NextToken().is(tok::l_brace)) return BracedCastResult; if (isStartOfObjCClassMessageMissingOpenBracket()) @@ -1271,7 +1298,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, if (isFollowedByParen) return TPResult::Ambiguous(); - if (getLangOpts().CPlusPlus0x && isFollowedByBrace) + if (getLangOpts().CPlusPlus11 && isFollowedByBrace) return BracedCastResult; return TPResult::True(); @@ -1386,7 +1413,7 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) { if (Next.is(tok::amp) || Next.is(tok::ampamp) || Next.is(tok::kw_const) || Next.is(tok::kw_volatile) || Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) || - Next.is(tok::l_square) || isCXX0XVirtSpecifier(Next) || + Next.is(tok::l_square) || isCXX11VirtSpecifier(Next) || Next.is(tok::l_brace) || Next.is(tok::kw_try) || Next.is(tok::equal) || Next.is(tok::arrow)) // The next token cannot appear after a constructor-style initializer, diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index f4cdd61..1ebba3e 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -12,15 +12,15 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" +#include "ParsePragma.h" +#include "RAIIObjectsForParser.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" #include "llvm/Support/raw_ostream.h" -#include "RAIIObjectsForParser.h" -#include "ParsePragma.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/ASTConsumer.h" using namespace clang; @@ -96,6 +96,11 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); } + if (getLangOpts().OpenMP) + OpenMPHandler.reset(new PragmaOpenMPHandler()); + else + OpenMPHandler.reset(new PragmaNoOpenMPHandler()); + PP.AddPragmaHandler(OpenMPHandler.get()); CommentSemaHandler.reset(new ActionCommentHandler(actions)); PP.addCommentHandler(CommentSemaHandler.get()); @@ -103,29 +108,6 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) PP.setCodeCompletionHandler(*this); } -/// If a crash happens while the parser is active, print out a line indicating -/// what the current token is. -void PrettyStackTraceParserEntry::print(raw_ostream &OS) const { - const Token &Tok = P.getCurToken(); - if (Tok.is(tok::eof)) { - OS << "<eof> parser at end of file\n"; - return; - } - - if (Tok.getLocation().isInvalid()) { - OS << "<unknown> parser at unknown location\n"; - return; - } - - const Preprocessor &PP = P.getPreprocessor(); - Tok.getLocation().print(OS, PP.getSourceManager()); - if (Tok.isAnnotation()) - OS << ": at annotation token \n"; - else - OS << ": current parser token '" << PP.getSpelling(Tok) << "'\n"; -} - - DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) { return Diags.Report(Loc, DiagID); } @@ -241,7 +223,7 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { // C++11 allows extra semicolons at namespace scope, but not in any of the // other contexts. if (Kind == OutsideFunction && getLangOpts().CPlusPlus) { - if (getLangOpts().CPlusPlus0x) + if (getLangOpts().CPlusPlus11) Diag(StartLoc, diag::warn_cxx98_compat_top_level_semi) << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); else @@ -451,6 +433,8 @@ Parser::~Parser() { OpenCLExtensionHandler.reset(); PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); } + PP.RemovePragmaHandler(OpenMPHandler.get()); + OpenMPHandler.reset(); PP.RemovePragmaHandler("STDC", FPContractHandler.get()); FPContractHandler.reset(); @@ -577,34 +561,18 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { } ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); Result = ParseExternalDeclaration(attrs); return false; } -/// ParseTranslationUnit: -/// translation-unit: [C99 6.9] -/// external-declaration -/// translation-unit external-declaration -void Parser::ParseTranslationUnit() { - Initialize(); - - DeclGroupPtrTy Res; - while (!ParseTopLevelDecl(Res)) - /*parse them all*/; - - ExitScope(); - assert(getCurScope() == 0 && "Scope imbalance!"); -} - /// ParseExternalDeclaration: /// /// external-declaration: [C99 6.9], declaration: [C++ dcl.dcl] /// function-definition /// declaration -/// [C++0x] empty-declaration /// [GNU] asm-definition /// [GNU] __extension__ external-declaration /// [OBJC] objc-class-definition @@ -616,8 +584,10 @@ void Parser::ParseTranslationUnit() { /// [C++] linkage-specification /// [GNU] asm-definition: /// simple-asm-expr ';' +/// [C++11] empty-declaration +/// [C++11] attribute-declaration /// -/// [C++0x] empty-declaration: +/// [C++11] empty-declaration: /// ';' /// /// [C++0x/GNU] 'extern' 'template' declaration @@ -661,10 +631,16 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_opencl_extension: HandlePragmaOpenCLExtension(); return DeclGroupPtrTy(); + case tok::annot_pragma_openmp: + ParseOpenMPDeclarativeDirective(); + return DeclGroupPtrTy(); case tok::semi: + // Either a C++11 empty-declaration or attribute-declaration. + SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), + attrs.getList(), + Tok.getLocation()); ConsumeExtraSemi(OutsideFunction); - // TODO: Invoke action for top-level semicolon. - return DeclGroupPtrTy(); + break; case tok::r_brace: Diag(Tok, diag::err_extraneous_closing_brace); ConsumeBrace(); @@ -764,7 +740,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // Extern templates SourceLocation ExternLoc = ConsumeToken(); SourceLocation TemplateLoc = ConsumeToken(); - Diag(ExternLoc, getLangOpts().CPlusPlus0x ? + Diag(ExternLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_extern_template : diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc); SourceLocation DeclEnd; @@ -783,11 +759,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, default: dont_know: // We can't tell whether this is a function-definition or declaration yet. - if (DS) { - return ParseDeclarationOrFunctionDefinition(attrs, DS); - } else { - return ParseDeclarationOrFunctionDefinition(attrs); - } + return ParseDeclarationOrFunctionDefinition(attrs, DS); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -986,7 +958,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (Tok.isNot(tok::equal)) { AttributeList *DtorAttrs = D.getAttributes(); while (DtorAttrs) { - if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName())) { + if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName()) && + !DtorAttrs->isCXX11Attribute()) { Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) << DtorAttrs->getName()->getName(); } @@ -1076,7 +1049,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, bool Delete = false; SourceLocation KWLoc; if (Tok.is(tok::kw_delete)) { - Diag(Tok, getLangOpts().CPlusPlus0x ? + Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_deleted_function : diag::ext_deleted_function); @@ -1084,7 +1057,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, Actions.SetDeclDeleted(Res, KWLoc); Delete = true; } else if (Tok.is(tok::kw_default)) { - Diag(Tok, getLangOpts().CPlusPlus0x ? + Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_defaulted_function : diag::ext_defaulted_function); @@ -1138,7 +1111,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. - ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope); + ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | Scope::DeclScope); // Read all the argument declarations. while (isDeclarationSpecifier()) { @@ -1263,7 +1237,8 @@ Parser::ExprResult Parser::ParseAsmStringLiteral() { return ExprError(); } default: - Diag(Tok, diag::err_expected_string_literal); + Diag(Tok, diag::err_expected_string_literal) + << /*Source='in...'*/0 << "'asm'"; return ExprError(); } @@ -1857,7 +1832,7 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { // Parse the declarations. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); DeclGroupPtrTy Result = ParseExternalDeclaration(attrs); if (Result && !getCurScope()->getParent()) @@ -1867,11 +1842,11 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { } Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) { - assert(Tok.isObjCAtKeyword(tok::objc___experimental_modules_import) && + assert(Tok.isObjCAtKeyword(tok::objc_import) && "Improper start to module import"); SourceLocation ImportLoc = ConsumeToken(); - llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path; + SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path; // Parse the module path. do { @@ -1909,7 +1884,9 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) { } bool BalancedDelimiterTracker::diagnoseOverflow() { - P.Diag(P.Tok, diag::err_parser_impl_limit_overflow); + P.Diag(P.Tok, diag::err_bracket_depth_exceeded) + << P.getLangOpts().BracketDepth; + P.Diag(P.Tok, diag::note_bracket_depth); P.SkipUntil(tok::eof); return true; } diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h index 060fd20..213950a 100644 --- a/lib/Parse/RAIIObjectsForParser.h +++ b/lib/Parse/RAIIObjectsForParser.h @@ -407,7 +407,7 @@ namespace clang { if (!P.Tok.is(Kind)) return true; - if (getDepth() < MaxDepth) { + if (getDepth() < P.getLangOpts().BracketDepth) { LOpen = (P.*Consumer)(); return false; } |