diff options
author | dim <dim@FreeBSD.org> | 2013-06-10 20:45:12 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-06-10 20:45:12 +0000 |
commit | ea266cad53e3d49771fa38103913d3ec7a166694 (patch) | |
tree | 8f7776b7310bebaf415ac5b69e46e9f928c37144 /lib/Parse | |
parent | c72c57c9e9b69944e3e009cd5e209634839581d3 (diff) | |
download | FreeBSD-src-ea266cad53e3d49771fa38103913d3ec7a166694.zip FreeBSD-src-ea266cad53e3d49771fa38103913d3ec7a166694.tar.gz |
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3
release):
http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_33/final@183502
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 39 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 256 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 79 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 11 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 22 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 96 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.h | 8 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 400 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 133 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 14 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 14 |
14 files changed, 897 insertions, 184 deletions
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt index 939998e..01c0694 100644 --- a/lib/Parse/CMakeLists.txt +++ b/lib/Parse/CMakeLists.txt @@ -17,6 +17,7 @@ add_clang_library(clangParse add_dependencies(clangParse ClangAttrClasses + ClangAttrExprArgs ClangAttrLateParsed ClangAttrList ClangAttrParsedAttrList diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index bc634b5..5fc4189 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -57,8 +57,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, if (FnD) { Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs, false, true); - bool TypeSpecContainsAuto - = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; + bool TypeSpecContainsAuto = D.getDeclSpec().containsPlaceholderType(); if (Init.isUsable()) Actions.AddInitializerToDecl(FnD, Init.get(), false, TypeSpecContainsAuto); @@ -279,8 +278,11 @@ void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() { void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); - if (HasTemplateScope) + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + if (HasTemplateScope) { Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); + ++CurTemplateDepthTracker; + } // The current scope is still active if we're the top-level class. // Otherwise we'll need to push and enter a new scope. @@ -301,9 +303,11 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // If this is a member template, introduce the template parameter scope. ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); - if (LM.TemplateScope) + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + if (LM.TemplateScope) { Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method); - + ++CurTemplateDepthTracker; + } // Start the delayed C++ method declaration Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method); @@ -379,9 +383,11 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { void Parser::ParseLexedMethodDefs(ParsingClass &Class) { bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); - if (HasTemplateScope) + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + if (HasTemplateScope) { Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); - + ++CurTemplateDepthTracker; + } bool HasClassScope = !Class.TopLevelClass; ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, HasClassScope); @@ -394,9 +400,11 @@ void Parser::ParseLexedMethodDefs(ParsingClass &Class) { void Parser::ParseLexedMethodDef(LexedMethod &LM) { // If this is a member template, introduce the template parameter scope. ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); - if (LM.TemplateScope) + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + if (LM.TemplateScope) { Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); - + ++CurTemplateDepthTracker; + } // Save the current token position. SourceLocation origLoc = Tok.getLocation(); @@ -441,6 +449,13 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { } else Actions.ActOnDefaultCtorInitializers(LM.D); + assert((Actions.getDiagnostics().hasErrorOccurred() || + !isa<FunctionTemplateDecl>(LM.D) || + cast<FunctionTemplateDecl>(LM.D)->getTemplateParameters()->getDepth() + < TemplateParameterDepth) && + "TemplateParameterDepth should be greater than the depth of " + "current template being instantiated!"); + ParseFunctionStatementBody(LM.D, FnScope); // Clear the late-template-parsed bit if we set it before. @@ -466,9 +481,11 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) { bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); - if (HasTemplateScope) + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + if (HasTemplateScope) { Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); - + ++CurTemplateDepthTracker; + } // Set or update the scope flags. bool AlreadyHasClassScope = Class.TopLevelClass; unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 990a909..6a87b78 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -178,6 +178,12 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } } +/// \brief Determine whether the given attribute has all expression arguments. +static bool attributeHasExprArgs(const IdentifierInfo &II) { + return llvm::StringSwitch<bool>(II.getName()) +#include "clang/Parse/AttrExprArgs.inc" + .Default(false); +} /// Parse the arguments to a parameterized GNU attribute or /// a C++11 attribute in "gnu" namespace. @@ -247,6 +253,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, TypeParsed = true; break; } + // If the attribute has all expression arguments, and not a "parameter", + // break out to handle it below. + if (attributeHasExprArgs(*AttrName)) + break; ParmName = Tok.getIdentifierInfo(); ParmLoc = ConsumeToken(); break; @@ -364,6 +374,7 @@ bool Parser::IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident) { .Case("novtable", true) .Case("selectany", true) .Case("thread", true) + .Case("safebuffers", true ) .Default(false); } @@ -394,17 +405,119 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, // The property declspec is more complex in that it can take one or two // assignment expressions as a parameter, but the lhs of the assignment // must be named get or put. - // - // For right now, we will just skip to the closing right paren of the - // property expression. - // - // FIXME: we should deal with __declspec(property) at some point because it - // is used in the platform SDK headers for the Parallel Patterns Library - // and ATL. - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, - Ident->getNameStart(), tok::r_paren)) + if (Tok.isNot(tok::l_paren)) { + Diag(Tok.getLocation(), diag::err_expected_lparen_after) + << Ident->getNameStart(); return; + } + BalancedDelimiterTracker T(*this, tok::l_paren); + T.expectAndConsume(diag::err_expected_lparen_after, + Ident->getNameStart(), tok::r_paren); + + enum AccessorKind { + AK_Invalid = -1, + AK_Put = 0, AK_Get = 1 // indices into AccessorNames + }; + IdentifierInfo *AccessorNames[] = { 0, 0 }; + bool HasInvalidAccessor = false; + + // Parse the accessor specifications. + while (true) { + // Stop if this doesn't look like an accessor spec. + if (!Tok.is(tok::identifier)) { + // If the user wrote a completely empty list, use a special diagnostic. + if (Tok.is(tok::r_paren) && !HasInvalidAccessor && + AccessorNames[AK_Put] == 0 && AccessorNames[AK_Get] == 0) { + Diag(Loc, diag::err_ms_property_no_getter_or_putter); + break; + } + + Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor); + break; + } + + AccessorKind Kind; + SourceLocation KindLoc = Tok.getLocation(); + StringRef KindStr = Tok.getIdentifierInfo()->getName(); + if (KindStr == "get") { + Kind = AK_Get; + } else if (KindStr == "put") { + Kind = AK_Put; + + // Recover from the common mistake of using 'set' instead of 'put'. + } else if (KindStr == "set") { + Diag(KindLoc, diag::err_ms_property_has_set_accessor) + << FixItHint::CreateReplacement(KindLoc, "put"); + Kind = AK_Put; + + // Handle the mistake of forgetting the accessor kind by skipping + // this accessor. + } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) { + Diag(KindLoc, diag::err_ms_property_missing_accessor_kind); + ConsumeToken(); + HasInvalidAccessor = true; + goto next_property_accessor; + + // Otherwise, complain about the unknown accessor kind. + } else { + Diag(KindLoc, diag::err_ms_property_unknown_accessor); + HasInvalidAccessor = true; + Kind = AK_Invalid; + + // Try to keep parsing unless it doesn't look like an accessor spec. + if (!NextToken().is(tok::equal)) break; + } + + // Consume the identifier. + ConsumeToken(); + + // Consume the '='. + if (Tok.is(tok::equal)) { + ConsumeToken(); + } else { + Diag(Tok.getLocation(), diag::err_ms_property_expected_equal) + << KindStr; + break; + } + + // Expect the method name. + if (!Tok.is(tok::identifier)) { + Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name); + break; + } + + if (Kind == AK_Invalid) { + // Just drop invalid accessors. + } else if (AccessorNames[Kind] != NULL) { + // Complain about the repeated accessor, ignore it, and keep parsing. + Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr; + } else { + AccessorNames[Kind] = Tok.getIdentifierInfo(); + } + ConsumeToken(); + + next_property_accessor: + // Keep processing accessors until we run out. + if (Tok.is(tok::comma)) { + ConsumeAnyToken(); + continue; + + // If we run into the ')', stop without consuming it. + } else if (Tok.is(tok::r_paren)) { + break; + } else { + Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen); + break; + } + } + + // Only add the property attribute if it was well-formed. + if (!HasInvalidAccessor) { + Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(), 0, + SourceLocation(), + AccessorNames[AK_Get], AccessorNames[AK_Put], + AttributeList::AS_Declspec); + } T.skipToEnd(); } else { // We don't recognize this as a valid declspec, but instead of creating the @@ -1489,35 +1602,42 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, MaybeParseGNUAttributes(D, &LateParsedAttrs); // Check to see if we have a function *definition* which must have a body. - if (AllowFunctionDefinitions && D.isFunctionDeclarator() && + if (D.isFunctionDeclarator() && // Look at the next token to make sure that this isn't a function // declaration. We have to check this because __attribute__ might be the // start of a function definition in GCC-extended K&R C. !isDeclarationAfterDeclarator()) { - if (isStartOfFunctionDefinition(D)) { - if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { - Diag(Tok, diag::err_function_declared_typedef); + if (AllowFunctionDefinitions) { + if (isStartOfFunctionDefinition(D)) { + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { + Diag(Tok, diag::err_function_declared_typedef); - // Recover by treating the 'typedef' as spurious. - DS.ClearStorageClassSpecs(); - } + // Recover by treating the 'typedef' as spurious. + DS.ClearStorageClassSpecs(); + } - Decl *TheDecl = - ParseFunctionDefinition(D, ParsedTemplateInfo(), &LateParsedAttrs); - return Actions.ConvertDeclToDeclGroup(TheDecl); - } + Decl *TheDecl = + ParseFunctionDefinition(D, ParsedTemplateInfo(), &LateParsedAttrs); + return Actions.ConvertDeclToDeclGroup(TheDecl); + } - if (isDeclarationSpecifier()) { - // If there is an invalid declaration specifier right after the function - // prototype, then we must be in a missing semicolon case where this isn't - // actually a body. Just fall through into the code that handles it as a - // prototype, and let the top-level code handle the erroneous declspec - // where it would otherwise expect a comma or semicolon. + if (isDeclarationSpecifier()) { + // If there is an invalid declaration specifier right after the function + // prototype, then we must be in a missing semicolon case where this isn't + // actually a body. Just fall through into the code that handles it as a + // prototype, and let the top-level code handle the erroneous declspec + // where it would otherwise expect a comma or semicolon. + } else { + Diag(Tok, diag::err_expected_fn_body); + SkipUntil(tok::semi); + return DeclGroupPtrTy(); + } } else { - Diag(Tok, diag::err_expected_fn_body); - SkipUntil(tok::semi); - return DeclGroupPtrTy(); + if (Tok.is(tok::l_brace)) { + Diag(Tok, diag::err_function_definition_not_allowed); + SkipUntil(tok::r_brace, true, true); + } } } @@ -1527,14 +1647,23 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we // must parse and analyze the for-range-initializer before the declaration is // analyzed. - if (FRI && Tok.is(tok::colon)) { - FRI->ColonLoc = ConsumeToken(); - if (Tok.is(tok::l_brace)) - FRI->RangeExpr = ParseBraceInitializer(); - else - FRI->RangeExpr = ParseExpression(); + // + // Handle the Objective-C for-in loop variable similarly, although we + // don't need to parse the container in advance. + if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) { + bool IsForRangeLoop = false; + if (Tok.is(tok::colon)) { + IsForRangeLoop = true; + FRI->ColonLoc = ConsumeToken(); + if (Tok.is(tok::l_brace)) + FRI->RangeExpr = ParseBraceInitializer(); + else + FRI->RangeExpr = ParseExpression(); + } + Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); - Actions.ActOnCXXForRangeDecl(ThisDecl); + if (IsForRangeLoop) + Actions.ActOnCXXForRangeDecl(ThisDecl); Actions.FinalizeDeclaration(ThisDecl); D.complete(ThisDecl); return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, &ThisDecl, 1); @@ -1691,8 +1820,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, } } - bool TypeContainsAuto = - D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; + bool TypeContainsAuto = D.getDeclSpec().containsPlaceholderType(); // Parse declarator '=' initializer. // If a '==' or '+=' is found, suggest a fixit to '='. @@ -1839,7 +1967,8 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, if (DS.getStorageClassSpecLoc().isValid()) Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass); else - Diag(DS.getThreadSpecLoc(), diag::err_typename_invalid_storageclass); + Diag(DS.getThreadStorageClassSpecLoc(), + diag::err_typename_invalid_storageclass); DS.ClearStorageClassSpecs(); } @@ -1920,10 +2049,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // error, do lookahead to try to do better recovery. This never applies // within a type specifier. Outside of C++, we allow this even if the // language doesn't "officially" support implicit int -- we support - // implicit int as an extension in C99 and C11. Allegedly, MS also - // supports implicit int in C++ mode. + // implicit int as an extension in C99 and C11. if (DSC != DSC_type_specifier && DSC != DSC_trailing && - (!getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt) && + !getLangOpts().CPlusPlus && isValidAfterIdentifierInDeclarator(NextToken())) { // If this token is valid for implicit int, e.g. "static x = 4", then // we just avoid eating the identifier, so it will be parsed as the @@ -2172,6 +2300,8 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, /// 'auto' /// 'register' /// [C++] 'mutable' +/// [C++11] 'thread_local' +/// [C11] '_Thread_local' /// [GNU] '__thread' /// function-specifier: [C99 6.7.4] /// [C99] 'inline' @@ -2608,7 +2738,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, PrevSpec, DiagID); break; case tok::kw_extern: - if (DS.isThreadSpecified()) + if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread) Diag(Tok, diag::ext_thread_before) << "extern"; isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc, PrevSpec, DiagID); @@ -2618,7 +2748,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, Loc, PrevSpec, DiagID); break; case tok::kw_static: - if (DS.isThreadSpecified()) + if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread) Diag(Tok, diag::ext_thread_before) << "static"; isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc, PrevSpec, DiagID); @@ -2647,7 +2777,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, PrevSpec, DiagID); break; case tok::kw___thread: - isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID); + isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc, + PrevSpec, DiagID); + break; + case tok::kw_thread_local: + isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc, + PrevSpec, DiagID); + break; + case tok::kw__Thread_local: + isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local, + Loc, PrevSpec, DiagID); break; // function-specifier @@ -3100,6 +3239,16 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, continue; } + if (Tok.is(tok::annot_pragma_pack)) { + HandlePragmaPack(); + continue; + } + + if (Tok.is(tok::annot_pragma_align)) { + HandlePragmaAlign(); + continue; + } + if (!Tok.is(tok::at)) { struct CFieldCallback : FieldCallback { Parser &P; @@ -3227,9 +3376,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, bool IsScopedUsingClassTag = false; // In C++11, recognize 'enum class' and 'enum struct'. - if (getLangOpts().CPlusPlus11 && - (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) { - Diag(Tok, diag::warn_cxx98_compat_scoped_enum); + if (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct)) { + Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum + : diag::ext_scoped_enum); IsScopedUsingClassTag = Tok.is(tok::kw_class); ScopedEnumKWLoc = ConsumeToken(); @@ -3614,8 +3763,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { MaybeParseGNUAttributes(attrs); Actions.ActOnEnumBody(StartLoc, T.getOpenLocation(), T.getCloseLocation(), - EnumDecl, EnumConstantDecls.data(), - EnumConstantDecls.size(), getCurScope(), + EnumDecl, EnumConstantDecls, + getCurScope(), attrs.getList()); EnumScope.Exit(); @@ -3894,6 +4043,8 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_auto: case tok::kw_register: case tok::kw___thread: + case tok::kw_thread_local: + case tok::kw__Thread_local: // Modules case tok::kw___module_private__: @@ -4873,7 +5024,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, Sema::CXXThisScopeRAII ThisScope(Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), DS.getTypeQualifiers() | - (D.getDeclSpec().isConstexprSpecified() + (D.getDeclSpec().isConstexprSpecified() && + !getLangOpts().CPlusPlus1y ? Qualifiers::Const : 0), IsCXX11MemberFunction); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index d7f8e98..f1fbbb1 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -674,15 +674,15 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ T.getCloseLocation()); } -/// ParseDecltypeSpecifier - Parse a C++0x decltype specifier. +/// ParseDecltypeSpecifier - Parse a C++11 decltype specifier. /// /// 'decltype' ( expression ) +/// 'decltype' ( 'auto' ) [C++1y] /// SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { assert((Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) && "Not a decltype specifier"); - ExprResult Result; SourceLocation StartLoc = Tok.getLocation(); SourceLocation EndLoc; @@ -709,29 +709,44 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { StartLoc : T.getOpenLocation(); } - // Parse the expression - - // C++0x [dcl.type.simple]p4: - // The operand of the decltype specifier is an unevaluated operand. - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, - 0, /*IsDecltype=*/true); - Result = ParseExpression(); - if (Result.isInvalid()) { - DS.SetTypeSpecError(); - if (SkipUntil(tok::r_paren, /*StopAtSemi=*/true, /*DontConsume=*/true)) { - EndLoc = ConsumeParen(); - } else { - if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) { - // Backtrack to get the location of the last token before the semi. - PP.RevertCachedTokens(2); - ConsumeToken(); // the semi. - EndLoc = ConsumeAnyToken(); - assert(Tok.is(tok::semi)); + // Check for C++1y 'decltype(auto)'. + if (Tok.is(tok::kw_auto)) { + // No need to disambiguate here: an expression can't start with 'auto', + // because the typename-specifier in a function-style cast operation can't + // be 'auto'. + Diag(Tok.getLocation(), + getLangOpts().CPlusPlus1y + ? diag::warn_cxx11_compat_decltype_auto_type_specifier + : diag::ext_decltype_auto_type_specifier); + ConsumeToken(); + } else { + // Parse the expression + + // C++11 [dcl.type.simple]p4: + // The operand of the decltype specifier is an unevaluated operand. + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, + 0, /*IsDecltype=*/true); + Result = ParseExpression(); + if (Result.isInvalid()) { + DS.SetTypeSpecError(); + if (SkipUntil(tok::r_paren, /*StopAtSemi=*/true, + /*DontConsume=*/true)) { + EndLoc = ConsumeParen(); } else { - EndLoc = Tok.getLocation(); + if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) { + // Backtrack to get the location of the last token before the semi. + PP.RevertCachedTokens(2); + ConsumeToken(); // the semi. + EndLoc = ConsumeAnyToken(); + assert(Tok.is(tok::semi)); + } else { + EndLoc = Tok.getLocation(); + } } + return EndLoc; } - return EndLoc; + + Result = Actions.ActOnDecltypeExpression(Result.take()); } // Match the ')' @@ -743,7 +758,6 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { return T.getCloseLocation(); } - Result = Actions.ActOnDecltypeExpression(Result.take()); if (Result.isInvalid()) { DS.SetTypeSpecError(); return T.getCloseLocation(); @@ -751,12 +765,16 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { EndLoc = T.getCloseLocation(); } + assert(!Result.isInvalid()); const char *PrevSpec = 0; unsigned DiagID; // Check for duplicate type specifiers (e.g. "int decltype(a)"). - if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec, - DiagID, Result.release())) { + if (Result.get() + ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec, + DiagID, Result.release()) + : DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, PrevSpec, + DiagID)) { Diag(StartLoc, DiagID) << PrevSpec; DS.SetTypeSpecError(); } @@ -773,8 +791,10 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec& DS, PP.EnterToken(Tok); Tok.setKind(tok::annot_decltype); - setExprAnnotation(Tok, DS.getTypeSpecType() == TST_decltype ? - DS.getRepAsExpr() : ExprResult()); + setExprAnnotation(Tok, + DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr() : + DS.getTypeSpecType() == TST_decltype_auto ? ExprResult() : + ExprError()); Tok.setAnnotationEndLoc(EndLoc); Tok.setLocation(StartLoc); PP.AnnotateCachedTokens(Tok); @@ -2267,11 +2287,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SkipUntil(tok::comma, true, true); else if (ThisDecl) Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid(), - DS.getTypeSpecType() == DeclSpec::TST_auto); + DS.containsPlaceholderType()); } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) { // No initializer. - Actions.ActOnUninitializedDecl(ThisDecl, - DS.getTypeSpecType() == DeclSpec::TST_auto); + Actions.ActOnUninitializedDecl(ThisDecl, DS.containsPlaceholderType()); } if (ThisDecl) { diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 956ba36..9521ffb 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -691,8 +691,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Res = getExprAnnotation(Tok); ConsumeToken(); break; - + case tok::kw_decltype: + // Annotate the token and tail recurse. + if (TryAnnotateTypeOrScopeToken()) + return ExprError(); + assert(Tok.isNot(tok::kw_decltype)); + return ParseCastExpression(isUnaryExpression, isAddressOfOperand); + case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant @@ -1408,8 +1414,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { CommaLocsTy CommaLocs; if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteCall(getCurScope(), LHS.get(), - ArrayRef<Expr *>()); + Actions.CodeCompleteCall(getCurScope(), LHS.get(), None); cutOffParsing(); return ExprError(); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 17c4adf..f259d5f 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1455,7 +1455,9 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, if (!InitExpr.isInvalid()) Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization, - DS.getTypeSpecType() == DeclSpec::TST_auto); + DS.containsPlaceholderType()); + else + Actions.ActOnInitializerError(DeclOut); // FIXME: Build a reference to this declaration? Convert it to bool? // (This is currently handled by Sema). @@ -2033,7 +2035,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Parse the conversion-declarator, which is merely a sequence of // ptr-operators. - Declarator D(DS, Declarator::TypeNameContext); + Declarator D(DS, Declarator::ConversionIdContext); ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); // Finish up the type. diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 3b96717..8311aa2 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -412,7 +412,7 @@ ExprResult Parser::ParseBraceInitializer() { if (!getLangOpts().CPlusPlus) Diag(LBraceLoc, diag::ext_gnu_empty_initializer); // Match the '}'. - return Actions.ActOnInitList(LBraceLoc, MultiExprArg(), ConsumeBrace()); + return Actions.ActOnInitList(LBraceLoc, None, ConsumeBrace()); } bool InitExprsOk = true; diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index ad95dd5..4a572f1 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -1565,6 +1565,13 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { if (Tok.is(tok::l_brace)) // we have ivars ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc); + else if (Tok.is(tok::less)) { // we have illegal '<' try to recover + Diag(Tok, diag::err_unexpected_protocol_qualifier); + // try to recover. + AttributeFactory attr; + DeclSpec DS(attr); + (void)ParseObjCProtocolQualifiers(DS); + } } assert(ObjCImpDecl); @@ -1675,7 +1682,7 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { /// Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { assert(Tok.isObjCAtKeyword(tok::objc_synthesize) && - "ParseObjCPropertyDynamic(): Expected '@synthesize'"); + "ParseObjCPropertySynthesize(): Expected '@synthesize'"); ConsumeToken(); // consume synthesize while (true) { @@ -2501,7 +2508,14 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, return ExprError(); } - ExprResult Res(ParseAssignmentExpression()); + ExprResult Expr; + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { + Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); + Expr = ParseBraceInitializer(); + } else + Expr = ParseAssignmentExpression(); + + ExprResult Res(Expr); if (Res.isInvalid()) { // We must manually skip to a ']', otherwise the expression skipper will // stop at the ']' when it skips to the ';'. We want it to skip beyond @@ -2747,7 +2761,9 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { if (Tok.is(tok::colon)) { ConsumeToken(); } else { - return ExprError(Diag(Tok, diag::err_expected_colon)); + Diag(Tok, diag::err_expected_colon); + SkipUntil(tok::r_brace); + return ExprError(); } ExprResult ValueExpr(ParseAssignmentExpression()); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index dc6b3ed..3d1249a 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -15,6 +15,8 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "clang/Sema/Scope.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; /// \brief Handle the annotation token produced for #pragma unused(...) @@ -122,6 +124,33 @@ void Parser::HandlePragmaFPContract() { ConsumeToken(); // The annotation token. } +StmtResult Parser::HandlePragmaCaptured() +{ + assert(Tok.is(tok::annot_pragma_captured)); + ConsumeToken(); + + if (Tok.isNot(tok::l_brace)) { + PP.Diag(Tok, diag::err_expected_lbrace); + return StmtError(); + } + + SourceLocation Loc = Tok.getLocation(); + + ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope); + Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, + /*NumParams=*/1); + + StmtResult R = ParseCompoundStatement(); + CapturedRegionScope.Exit(); + + if (R.isInvalid()) { + Actions.ActOnCapturedRegionError(); + return StmtError(); + } + + return Actions.ActOnCapturedRegionEnd(R.get()); +} + namespace { typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData; } @@ -151,6 +180,8 @@ void Parser::HandlePragmaOpenCLExtension() { } } + + // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -762,3 +793,68 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, PP.EnterTokenStream(Toks, Pragma.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); } + +/// \brief Handle the microsoft \#pragma comment extension. +/// +/// The syntax is: +/// \code +/// #pragma comment(linker, "foo") +/// \endcode +/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. +/// "foo" is a string, which is fully macro expanded, and permits string +/// concatenation, embedded escape characters etc. See MSDN for more details. +void PragmaCommentHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + SourceLocation CommentLoc = Tok.getLocation(); + PP.Lex(Tok); + if (Tok.isNot(tok::l_paren)) { + PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); + return; + } + + // Read the identifier. + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); + return; + } + + // Verify that this is one of the 5 whitelisted options. + // FIXME: warn that 'exestr' is deprecated. + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") && + !II->isStr("linker") && !II->isStr("user")) { + PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); + return; + } + + // Read the optional string if present. + PP.Lex(Tok); + std::string ArgumentString; + if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, + "pragma comment", + /*MacroExpansion=*/true)) + return; + + // FIXME: If the kind is "compiler" warn if the string is present (it is + // ignored). + // FIXME: 'lib' requires a comment string. + // FIXME: 'linker' requires a comment string, and has a specific list of + // things that are allowable. + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); + return; + } + PP.Lex(Tok); // eat the r_paren. + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); + return; + } + + // If the pragma is lexically sound, notify any interested PPCallbacks. + if (PP.getPPCallbacks()) + PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); +} diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h index 841a60b..d9560f3 100644 --- a/lib/Parse/ParsePragma.h +++ b/lib/Parse/ParsePragma.h @@ -113,6 +113,14 @@ public: Token &FirstToken); }; +/// PragmaCommentHandler - "\#pragma comment ...". +class PragmaCommentHandler : public PragmaHandler { +public: + PragmaCommentHandler() : PragmaHandler("comment") {} + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); +}; + } // end namespace clang #endif diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 355f369..43b6965 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -14,13 +14,26 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/AST/ASTContext.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -289,6 +302,9 @@ Retry: HandlePragmaOpenCLExtension(); return StmtEmpty(); + case tok::annot_pragma_captured: + return HandlePragmaCaptured(); + case tok::annot_pragma_openmp: SourceLocation DeclStart = Tok.getLocation(); DeclGroupPtrTy Res = ParseOpenMPDeclarativeDirective(); @@ -1660,6 +1676,281 @@ StmtResult Parser::ParseReturnStatement() { return Actions.ActOnReturnStmt(ReturnLoc, R.take()); } +namespace { + class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback { + Parser &TheParser; + SourceLocation AsmLoc; + StringRef AsmString; + + /// The tokens we streamed into AsmString and handed off to MC. + ArrayRef<Token> AsmToks; + + /// The offset of each token in AsmToks within AsmString. + ArrayRef<unsigned> AsmTokOffsets; + + public: + ClangAsmParserCallback(Parser &P, SourceLocation Loc, + StringRef AsmString, + ArrayRef<Token> Toks, + ArrayRef<unsigned> Offsets) + : TheParser(P), AsmLoc(Loc), AsmString(AsmString), + AsmToks(Toks), AsmTokOffsets(Offsets) { + assert(AsmToks.size() == AsmTokOffsets.size()); + } + + void *LookupInlineAsmIdentifier(StringRef &LineBuf, + InlineAsmIdentifierInfo &Info, + bool IsUnevaluatedContext) { + // Collect the desired tokens. + SmallVector<Token, 16> LineToks; + const Token *FirstOrigToken = 0; + findTokensForString(LineBuf, LineToks, FirstOrigToken); + + unsigned NumConsumedToks; + ExprResult Result = + TheParser.ParseMSAsmIdentifier(LineToks, NumConsumedToks, &Info, + IsUnevaluatedContext); + + // If we consumed the entire line, tell MC that. + // Also do this if we consumed nothing as a way of reporting failure. + if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) { + // By not modifying LineBuf, we're implicitly consuming it all. + + // Otherwise, consume up to the original tokens. + } else { + assert(FirstOrigToken && "not using original tokens?"); + + // Since we're using original tokens, apply that offset. + assert(FirstOrigToken[NumConsumedToks].getLocation() + == LineToks[NumConsumedToks].getLocation()); + unsigned FirstIndex = FirstOrigToken - AsmToks.begin(); + unsigned LastIndex = FirstIndex + NumConsumedToks - 1; + + // The total length we've consumed is the relative offset + // of the last token we consumed plus its length. + unsigned TotalOffset = (AsmTokOffsets[LastIndex] + + AsmToks[LastIndex].getLength() + - AsmTokOffsets[FirstIndex]); + LineBuf = LineBuf.substr(0, TotalOffset); + } + + // Initialize the "decl" with the lookup result. + Info.OpDecl = static_cast<void*>(Result.take()); + return Info.OpDecl; + } + + bool LookupInlineAsmField(StringRef Base, StringRef Member, + unsigned &Offset) { + return TheParser.getActions().LookupInlineAsmField(Base, Member, + Offset, AsmLoc); + } + + static void DiagHandlerCallback(const llvm::SMDiagnostic &D, + void *Context) { + ((ClangAsmParserCallback*) Context)->handleDiagnostic(D); + } + + private: + /// Collect the appropriate tokens for the given string. + void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks, + const Token *&FirstOrigToken) const { + // For now, assert that the string we're working with is a substring + // of what we gave to MC. This lets us use the original tokens. + assert(!std::less<const char*>()(Str.begin(), AsmString.begin()) && + !std::less<const char*>()(AsmString.end(), Str.end())); + + // Try to find a token whose offset matches the first token. + unsigned FirstCharOffset = Str.begin() - AsmString.begin(); + const unsigned *FirstTokOffset + = std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), + FirstCharOffset); + + // For now, assert that the start of the string exactly + // corresponds to the start of a token. + assert(*FirstTokOffset == FirstCharOffset); + + // Use all the original tokens for this line. (We assume the + // end of the line corresponds cleanly to a token break.) + unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin(); + FirstOrigToken = &AsmToks[FirstTokIndex]; + unsigned LastCharOffset = Str.end() - AsmString.begin(); + for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) { + if (AsmTokOffsets[i] >= LastCharOffset) break; + TempToks.push_back(AsmToks[i]); + } + } + + void handleDiagnostic(const llvm::SMDiagnostic &D) { + // Compute an offset into the inline asm buffer. + // FIXME: This isn't right if .macro is involved (but hopefully, no + // real-world code does that). + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + const llvm::MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); + + // Figure out which token that offset points into. + const unsigned *TokOffsetPtr = + std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset); + unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin(); + unsigned TokOffset = *TokOffsetPtr; + + // If we come up with an answer which seems sane, use it; otherwise, + // just point at the __asm keyword. + // FIXME: Assert the answer is sane once we handle .macro correctly. + SourceLocation Loc = AsmLoc; + if (TokIndex < AsmToks.size()) { + const Token &Tok = AsmToks[TokIndex]; + Loc = Tok.getLocation(); + Loc = Loc.getLocWithOffset(Offset - TokOffset); + } + TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) + << D.getMessage(); + } + }; +} + +/// Parse an identifier in an MS-style inline assembly block. +/// +/// \param CastInfo - a void* so that we don't have to teach Parser.h +/// about the actual type. +ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, + unsigned &NumLineToksConsumed, + void *CastInfo, + bool IsUnevaluatedContext) { + llvm::InlineAsmIdentifierInfo &Info = + *(llvm::InlineAsmIdentifierInfo *) CastInfo; + + // Push a fake token on the end so that we don't overrun the token + // stream. We use ';' because it expression-parsing should never + // overrun it. + const tok::TokenKind EndOfStream = tok::semi; + Token EndOfStreamTok; + EndOfStreamTok.startToken(); + EndOfStreamTok.setKind(EndOfStream); + LineToks.push_back(EndOfStreamTok); + + // Also copy the current token over. + LineToks.push_back(Tok); + + PP.EnterTokenStream(LineToks.begin(), + LineToks.size(), + /*disable macros*/ true, + /*owns tokens*/ false); + + // Clear the current token and advance to the first token in LineToks. + ConsumeAnyToken(); + + // Parse an optional scope-specifier if we're in C++. + CXXScopeSpec SS; + if (getLangOpts().CPlusPlus) { + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + } + + // Require an identifier here. + SourceLocation TemplateKWLoc; + UnqualifiedId Id; + bool Invalid = ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, + /*ObjectType=*/ ParsedType(), + TemplateKWLoc, + Id); + + // If we've run into the poison token we inserted before, or there + // was a parsing error, then claim the entire line. + if (Invalid || Tok.is(EndOfStream)) { + NumLineToksConsumed = LineToks.size() - 2; + + // Otherwise, claim up to the start of the next token. + } else { + // Figure out how many tokens we are into LineToks. + unsigned LineIndex = 0; + while (LineToks[LineIndex].getLocation() != Tok.getLocation()) { + LineIndex++; + assert(LineIndex < LineToks.size() - 2); // we added two extra tokens + } + + NumLineToksConsumed = LineIndex; + } + + // Finally, restore the old parsing state by consuming all the + // tokens we staged before, implicitly killing off the + // token-lexer we pushed. + for (unsigned n = LineToks.size() - 2 - NumLineToksConsumed; n != 0; --n) { + ConsumeAnyToken(); + } + ConsumeToken(EndOfStream); + + // Leave LineToks in its original state. + LineToks.pop_back(); + LineToks.pop_back(); + + // Perform the lookup. + return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, + IsUnevaluatedContext); +} + +/// Turn a sequence of our tokens back into a string that we can hand +/// to the MC asm parser. +static bool buildMSAsmString(Preprocessor &PP, + SourceLocation AsmLoc, + ArrayRef<Token> AsmToks, + SmallVectorImpl<unsigned> &TokOffsets, + SmallString<512> &Asm) { + assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); + + // Is this the start of a new assembly statement? + bool isNewStatement = true; + + for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { + const Token &Tok = AsmToks[i]; + + // Start each new statement with a newline and a tab. + if (!isNewStatement && + (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) { + Asm += "\n\t"; + isNewStatement = true; + } + + // Preserve the existence of leading whitespace except at the + // start of a statement. + if (!isNewStatement && Tok.hasLeadingSpace()) + Asm += ' '; + + // Remember the offset of this token. + TokOffsets.push_back(Asm.size()); + + // Don't actually write '__asm' into the assembly stream. + if (Tok.is(tok::kw_asm)) { + // Complain about __asm at the end of the stream. + if (i + 1 == e) { + PP.Diag(AsmLoc, diag::err_asm_empty); + return true; + } + + continue; + } + + // Append the spelling of the token. + SmallString<32> SpellingBuffer; + bool SpellingInvalid = false; + Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid); + assert(!SpellingInvalid && "spelling was invalid after correct parse?"); + + // We are no longer at the start of a statement. + isNewStatement = false; + } + + // Ensure that the buffer is null-terminated. + Asm.push_back('\0'); + Asm.pop_back(); + + assert(TokOffsets.size() == AsmToks.size()); + return false; +} + /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, /// this routine is called to collect the tokens for an MS asm statement. /// @@ -1768,9 +2059,114 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { return StmtError(); } + // Okay, prepare to use MC to parse the assembly. + SmallVector<StringRef, 4> ConstraintRefs; + SmallVector<Expr*, 4> Exprs; + SmallVector<StringRef, 4> ClobberRefs; + + // We need an actual supported target. + llvm::Triple TheTriple = Actions.Context.getTargetInfo().getTriple(); + llvm::Triple::ArchType ArchTy = TheTriple.getArch(); + bool UnsupportedArch = (ArchTy != llvm::Triple::x86 && + ArchTy != llvm::Triple::x86_64); + if (UnsupportedArch) + Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); + + // If we don't support assembly, or the assembly is empty, we don't + // need to instantiate the AsmParser, etc. + if (UnsupportedArch || AsmToks.empty()) { + return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, StringRef(), + /*NumOutputs*/ 0, /*NumInputs*/ 0, + ConstraintRefs, ClobberRefs, Exprs, EndLoc); + } + + // Expand the tokens into a string buffer. + SmallString<512> AsmString; + SmallVector<unsigned, 8> TokOffsets; + if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString)) + return StmtError(); + + // Find the target and create the target specific parser. + std::string Error; + const std::string &TT = TheTriple.getTriple(); + const llvm::Target *TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error); + + OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); + OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); + OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); + OwningPtr<llvm::MCSubtargetInfo> + STI(TheTarget->createMCSubtargetInfo(TT, "", "")); + + llvm::SourceMgr TempSrcMgr; + llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &TempSrcMgr); + llvm::MemoryBuffer *Buffer = + llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>"); + + // Tell SrcMgr about this buffer, which is what the parser will pick up. + TempSrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); + + OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); + OwningPtr<llvm::MCAsmParser> + Parser(createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI)); + OwningPtr<llvm::MCTargetAsmParser> + TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); + + // Get the instruction descriptor. + const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); + llvm::MCInstPrinter *IP = + TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); + + // Change to the Intel dialect. + Parser->setAssemblerDialect(1); + Parser->setTargetParser(*TargetParser.get()); + Parser->setParsingInlineAsm(true); + TargetParser->setParsingInlineAsm(true); + + ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, + AsmToks, TokOffsets); + TargetParser->setSemaCallback(&Callback); + TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback, + &Callback); + + unsigned NumOutputs; + unsigned NumInputs; + std::string AsmStringIR; + SmallVector<std::pair<void *, bool>, 4> OpExprs; + SmallVector<std::string, 4> Constraints; + SmallVector<std::string, 4> Clobbers; + if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, + NumOutputs, NumInputs, OpExprs, Constraints, + Clobbers, MII, IP, Callback)) + return StmtError(); + + // Build the vector of clobber StringRefs. + unsigned NumClobbers = Clobbers.size(); + ClobberRefs.resize(NumClobbers); + for (unsigned i = 0; i != NumClobbers; ++i) + ClobberRefs[i] = StringRef(Clobbers[i]); + + // Recast the void pointers and build the vector of constraint StringRefs. + unsigned NumExprs = NumOutputs + NumInputs; + ConstraintRefs.resize(NumExprs); + Exprs.resize(NumExprs); + for (unsigned i = 0, e = NumExprs; i != e; ++i) { + Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first); + if (!OpExpr) + return StmtError(); + + // Need address of variable. + if (OpExprs[i].second) + OpExpr = Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr) + .take(); + + ConstraintRefs[i] = StringRef(Constraints[i]); + Exprs[i] = OpExpr; + } + // FIXME: We should be passing source locations for better diagnostics. - return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, - llvm::makeArrayRef(AsmToks), EndLoc); + return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, AsmStringIR, + NumOutputs, NumInputs, + ConstraintRefs, ClobberRefs, Exprs, EndLoc); } /// ParseAsmStatement - Parse a GNU extended asm statement. diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index f146669..84b7df7 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -39,28 +39,7 @@ Parser::ParseDeclarationStartingWithTemplate(unsigned Context, AccessAttrs); } -/// \brief RAII class that manages the template parameter depth. -namespace { - class TemplateParameterDepthCounter { - unsigned &Depth; - unsigned AddedLevels; - - public: - explicit TemplateParameterDepthCounter(unsigned &Depth) - : Depth(Depth), AddedLevels(0) { } - - ~TemplateParameterDepthCounter() { - Depth -= AddedLevels; - } - void operator++() { - ++Depth; - ++AddedLevels; - } - - operator unsigned() const { return Depth; } - }; -} /// \brief Parse a template declaration or an explicit specialization. /// @@ -117,7 +96,8 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, bool isSpecialization = true; bool LastParamListWasEmpty = false; TemplateParameterLists ParamLists; - TemplateParameterDepthCounter Depth(TemplateParameterDepth); + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + do { // Consume the 'export', if any. SourceLocation ExportLoc; @@ -137,8 +117,8 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, // Parse the '<' template-parameter-list '>' SourceLocation LAngleLoc, RAngleLoc; SmallVector<Decl*, 4> TemplateParams; - if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc, - RAngleLoc)) { + if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(), + TemplateParams, LAngleLoc, RAngleLoc)) { // Skip until the semi-colon or a }. SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) @@ -147,14 +127,15 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, } ParamLists.push_back( - Actions.ActOnTemplateParameterList(Depth, ExportLoc, + Actions.ActOnTemplateParameterList(CurTemplateDepthTracker.getDepth(), + ExportLoc, TemplateLoc, LAngleLoc, TemplateParams.data(), TemplateParams.size(), RAngleLoc)); if (!TemplateParams.empty()) { isSpecialization = false; - ++Depth; + ++CurTemplateDepthTracker; } else { LastParamListWasEmpty = true; } @@ -1168,6 +1149,9 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { /// template-argument-list ',' template-argument bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { + // Template argument lists are constant-evaluation contexts. + EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated); + while (true) { ParsedTemplateArgument Arg = ParseTemplateArgument(); if (Tok.is(tok::ellipsis)) { @@ -1249,53 +1233,56 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { return; // Get the FunctionDecl. - FunctionDecl *FD = 0; - if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D)) - FD = FunTmpl->getTemplatedDecl(); - else - FD = cast<FunctionDecl>(LMT.D); + FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LMT.D); + FunctionDecl *FunD = + FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LMT.D); + // Track template parameter depth. + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); // To restore the context after late parsing. Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext); SmallVector<ParseScope*, 4> TemplateParamScopeStack; - DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD); - if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { - TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope)); - Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); - Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); - } else { - // Get the list of DeclContext to reenter. - SmallVector<DeclContext*, 4> DeclContextToReenter; - DeclContext *DD = FD->getLexicalParent(); - while (DD && !DD->isTranslationUnit()) { - DeclContextToReenter.push_back(DD); - DD = DD->getLexicalParent(); - } - // Reenter template scopes from outmost to innermost. - SmallVector<DeclContext*, 4>::reverse_iterator II = - DeclContextToReenter.rbegin(); - for (; II != DeclContextToReenter.rend(); ++II) { - if (ClassTemplatePartialSpecializationDecl* MD = - dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) { - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope)); - Actions.ActOnReenterTemplateScope(getCurScope(), MD); - } else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) { - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope, - MD->getDescribedClassTemplate() != 0 )); - Actions.ActOnReenterTemplateScope(getCurScope(), - MD->getDescribedClassTemplate()); - } - TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); - Actions.PushDeclContext(Actions.getCurScope(), *II); + // Get the list of DeclContexts to reenter. + SmallVector<DeclContext*, 4> DeclContextsToReenter; + DeclContext *DD = FunD->getLexicalParent(); + while (DD && !DD->isTranslationUnit()) { + DeclContextsToReenter.push_back(DD); + DD = DD->getLexicalParent(); + } + + // Reenter template scopes from outermost to innermost. + SmallVector<DeclContext*, 4>::reverse_iterator II = + DeclContextsToReenter.rbegin(); + for (; II != DeclContextsToReenter.rend(); ++II) { + if (ClassTemplatePartialSpecializationDecl *MD = + dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) { + TemplateParamScopeStack.push_back( + new ParseScope(this, Scope::TemplateParamScope)); + Actions.ActOnReenterTemplateScope(getCurScope(), MD); + ++CurTemplateDepthTracker; + } else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) { + bool ManageScope = MD->getDescribedClassTemplate() != 0; + TemplateParamScopeStack.push_back( + new ParseScope(this, Scope::TemplateParamScope, ManageScope)); + Actions.ActOnReenterTemplateScope(getCurScope(), + MD->getDescribedClassTemplate()); + ++CurTemplateDepthTracker; } - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope)); - Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); + TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); + Actions.PushDeclContext(Actions.getCurScope(), *II); } + TemplateParamScopeStack.push_back( + new ParseScope(this, Scope::TemplateParamScope)); + + DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD); + if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { + Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); + ++CurTemplateDepthTracker; + } + Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); + ++CurTemplateDepthTracker; assert(!LMT.Toks.empty() && "Empty body!"); @@ -1314,15 +1301,9 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); // Recreate the containing function DeclContext. - Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FD)); - - if (FunctionTemplateDecl *FunctionTemplate - = dyn_cast_or_null<FunctionTemplateDecl>(LMT.D)) - Actions.ActOnStartOfFunctionDef(getCurScope(), - FunctionTemplate->getTemplatedDecl()); - if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D)) - Actions.ActOnStartOfFunctionDef(getCurScope(), Function); + Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FunD)); + Actions.ActOnStartOfFunctionDef(getCurScope(), FunD); if (Tok.is(tok::kw_try)) { ParseFunctionTryBlock(LMT.D, FnScope); @@ -1333,8 +1314,12 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { Actions.ActOnDefaultCtorInitializers(LMT.D); if (Tok.is(tok::l_brace)) { + assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() < + TemplateParameterDepth) && + "TemplateParameterDepth should be greater than the depth of " + "current template being instantiated!"); ParseFunctionStatementBody(LMT.D, FnScope); - Actions.MarkAsLateParsedTemplate(FD, false); + Actions.MarkAsLateParsedTemplate(FunD, false); } else Actions.ActOnFinishFunctionBody(LMT.D, 0); } diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 5e0ef2b..dff3b64 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -837,11 +837,12 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw___underlying_type: - case tok::kw_thread_local: case tok::kw__Decimal32: case tok::kw__Decimal64: case tok::kw__Decimal128: case tok::kw___thread: + case tok::kw_thread_local: + case tok::kw__Thread_local: case tok::kw_typeof: case tok::kw___cdecl: case tok::kw___stdcall: @@ -893,7 +894,7 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) { /// function-specifier /// 'friend' /// 'typedef' -/// [C++0x] 'constexpr' +/// [C++11] 'constexpr' /// [GNU] attributes declaration-specifiers[opt] /// /// storage-class-specifier: @@ -903,6 +904,8 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) { /// 'mutable' /// 'auto' /// [GNU] '__thread' +/// [C++11] 'thread_local' +/// [C11] '_Thread_local' /// /// function-specifier: /// 'inline' @@ -937,8 +940,9 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) { /// 'void' /// [GNU] typeof-specifier /// [GNU] '_Complex' -/// [C++0x] 'auto' [TODO] -/// [C++0x] 'decltype' ( expression ) +/// [C++11] 'auto' +/// [C++11] 'decltype' ( expression ) +/// [C++1y] 'decltype' ( 'auto' ) /// /// type-name: /// class-name @@ -1073,6 +1077,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw_mutable: case tok::kw_auto: case tok::kw___thread: + case tok::kw_thread_local: + case tok::kw__Thread_local: // function-specifier case tok::kw_inline: case tok::kw_virtual: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 1ebba3e..455139b 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -102,6 +102,11 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) OpenMPHandler.reset(new PragmaNoOpenMPHandler()); PP.AddPragmaHandler(OpenMPHandler.get()); + if (getLangOpts().MicrosoftExt) { + MSCommentHandler.reset(new PragmaCommentHandler()); + PP.AddPragmaHandler(MSCommentHandler.get()); + } + CommentSemaHandler.reset(new ActionCommentHandler(actions)); PP.addCommentHandler(CommentSemaHandler.get()); @@ -436,6 +441,11 @@ Parser::~Parser() { PP.RemovePragmaHandler(OpenMPHandler.get()); OpenMPHandler.reset(); + if (getLangOpts().MicrosoftExt) { + PP.RemovePragmaHandler(MSCommentHandler.get()); + MSCommentHandler.reset(); + } + PP.RemovePragmaHandler("STDC", FPContractHandler.get()); FPContractHandler.reset(); @@ -1141,8 +1151,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { diag::err_invalid_storage_class_in_func_decl); DS.ClearStorageClassSpecs(); } - if (DS.isThreadSpecified()) { - Diag(DS.getThreadSpecLoc(), + if (DS.getThreadStorageClassSpec() != DeclSpec::TSCS_unspecified) { + Diag(DS.getThreadStorageClassSpecLoc(), diag::err_invalid_storage_class_in_func_decl); DS.ClearStorageClassSpecs(); } |