diff options
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 101 |
1 files changed, 72 insertions, 29 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 298a2bad56..c4f02b9b99 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1,9 +1,8 @@ //===--- ParseDecl.cpp - Declaration Parsing --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -223,6 +222,15 @@ static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) { #undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST } +/// Determine whether the given attribute treats kw_this as an identifier. +static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II) { +#define CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST + return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) +#include "clang/Parse/AttrParserStringSwitches.inc" + .Default(false); +#undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST +} + /// Determine whether the given attribute parses a type argument. static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { #define CLANG_ATTR_TYPE_ARG_LIST @@ -287,6 +295,12 @@ unsigned Parser::ParseAttributeArgsCommon( // Ignore the left paren location for now. ConsumeParen(); + bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName); + + // Interpret "kw_this" as an identifier if the attributed requests it. + if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) + Tok.setKind(tok::identifier); + ArgsVector ArgExprs; if (Tok.is(tok::identifier)) { // If this attribute wants an 'identifier' argument, make it so. @@ -314,6 +328,10 @@ unsigned Parser::ParseAttributeArgsCommon( // Parse the non-empty comma-separated list of expressions. do { + // Interpret "kw_this" as an identifier if the attributed requests it. + if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) + Tok.setKind(tok::identifier); + ExprResult ArgExpr; if (Tok.is(tok::identifier) && attributeHasVariadicIdentifierArg(*AttrName)) { @@ -1716,7 +1734,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, /// [C++11] attribute-specifier-seq decl-specifier-seq[opt] /// init-declarator-list ';' ///[C90/C++]init-declarator-list ';' [TODO] -/// [OMP] threadprivate-directive [TODO] +/// [OMP] threadprivate-directive +/// [OMP] allocate-directive [TODO] /// /// for-range-declaration: [C++11 6.5p1: stmt.ranged] /// attribute-specifier-seq[opt] type-specifier-seq declarator @@ -2275,7 +2294,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( return nullptr; } - ExprResult Init(ParseInitializer()); + PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl); + ExprResult Init = ParseInitializer(); // If this is the only decl in (possibly) range based for statement, // our best guess is that the user meant ':' instead of '='. @@ -2313,25 +2333,27 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( InitializerScopeRAII InitScope(*this, D, ThisDecl); - llvm::function_ref<void()> ExprListCompleter; auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl); - auto ConstructorCompleter = [&, ThisVarDecl] { + auto RunSignatureHelp = [&]() { QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), ThisDecl->getLocation(), Exprs, T.getOpenLocation()); CalledSignatureHelp = true; - Actions.CodeCompleteExpression(getCurScope(), PreferredType); + return PreferredType; }; + auto SetPreferredType = [&] { + PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); + }; + + llvm::function_ref<void()> ExpressionStarts; if (ThisVarDecl) { // ParseExpressionList can sometimes succeed even when ThisDecl is not // VarDecl. This is an error and it is reported in a call to // Actions.ActOnInitializerError(). However, we call - // ProduceConstructorSignatureHelp only on VarDecls, falling back to - // default completer in other cases. - ExprListCompleter = ConstructorCompleter; + // ProduceConstructorSignatureHelp only on VarDecls. + ExpressionStarts = SetPreferredType; } - - if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) { + if (ParseExpressionList(Exprs, CommaLocs, ExpressionStarts)) { if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) { Actions.ProduceConstructorSignatureHelp( getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), @@ -2627,6 +2649,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, case tok::semi: // This looks like a variable or function declaration. The type is // probably missing. We're done parsing decl-specifiers. + // But only if we are not in a function prototype scope. + if (getCurScope()->isFunctionPrototypeScope()) + break; if (SS) AnnotateScopeToken(*SS, /*IsNewAnnotation*/false); return false; @@ -2832,7 +2857,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, IdentifierInfo *Name = AfterScope.getIdentifierInfo(); Sema::NameClassification Classification = Actions.ClassifyName( getCurScope(), SS, Name, AfterScope.getLocation(), Next, - /*IsAddressOfOperand*/false); + /*IsAddressOfOperand=*/false, /*CCC=*/nullptr); switch (Classification.getKind()) { case Sema::NC_Error: SkipMalformedDecl(); @@ -3790,19 +3815,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, getLangOpts()); break; - // OpenCL access qualifiers: - case tok::kw___read_only: - case tok::kw___write_only: - case tok::kw___read_write: - // OpenCL C++ 1.0 s2.2: access qualifiers are reserved keywords. - if (Actions.getLangOpts().OpenCLCPlusPlus) { - DiagID = diag::err_openclcxx_reserved; - PrevSpec = Tok.getIdentifierInfo()->getNameStart(); - isInvalid = true; - } - ParseOpenCLQualifiers(DS.getAttributes()); - break; - // OpenCL address space qualifiers: case tok::kw___generic: // generic address space is introduced only in OpenCL v2.0 @@ -3815,10 +3827,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; }; LLVM_FALLTHROUGH; + case tok::kw_private: case tok::kw___private: case tok::kw___global: case tok::kw___local: case tok::kw___constant: + // OpenCL access qualifiers: + case tok::kw___read_only: + case tok::kw___write_only: + case tok::kw___read_write: ParseOpenCLQualifiers(DS.getAttributes()); break; @@ -3876,6 +3893,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, /// ParseStructDeclaration - Parse a struct declaration without the terminating /// semicolon. /// +/// Note that a struct declaration refers to a declaration in a struct, +/// not to the declaration of a struct. +/// /// struct-declaration: /// [C2x] attributes-specifier-seq[opt] /// specifier-qualifier-list struct-declarator-list @@ -4782,9 +4802,11 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___read_only: case tok::kw___read_write: case tok::kw___write_only: - return true; + case tok::kw_private: + return getLangOpts().OpenCL; + // C11 _Atomic case tok::kw__Atomic: return true; @@ -4976,6 +4998,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { #include "clang/Basic/OpenCLImageTypes.def" return true; + + case tok::kw_private: + return getLangOpts().OpenCL; } } @@ -5176,6 +5201,10 @@ void Parser::ParseTypeQualifierListOpt( break; // OpenCL qualifiers: + case tok::kw_private: + if (!getLangOpts().OpenCL) + goto DoneWithTypeQuals; + LLVM_FALLTHROUGH; case tok::kw___private: case tok::kw___global: case tok::kw___local: @@ -6159,6 +6188,20 @@ void Parser::ParseFunctionDeclarator(Declarator &D, Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers()); if (D.getDeclSpec().isConstexprSpecified() && !getLangOpts().CPlusPlus14) Q.addConst(); + // FIXME: Collect C++ address spaces. + // If there are multiple different address spaces, the source is invalid. + // Carry on using the first addr space for the qualifiers of 'this'. + // The diagnostic will be given later while creating the function + // prototype for the method. + if (getLangOpts().OpenCLCPlusPlus) { + for (ParsedAttr &attr : DS.getAttributes()) { + LangAS ASIdx = attr.asOpenCLLangAS(); + if (ASIdx != LangAS::Default) { + Q.addAddressSpace(ASIdx); + break; + } + } + } Sema::CXXThisScopeRAII ThisScope( Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q, |