aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r--lib/Parse/ParseDecl.cpp101
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,