summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2015-07-05 14:23:59 +0000
committerdim <dim@FreeBSD.org>2015-07-05 14:23:59 +0000
commite7bcad327814a78ecb8d5f5545d2e3df84c67a5c (patch)
treeac719b5984165053bf83d71142e4d96b609b9784 /lib/Sema
parent9dd834653b811ad20382e98a87dff824980c9916 (diff)
downloadFreeBSD-src-e7bcad327814a78ecb8d5f5545d2e3df84c67a5c.zip
FreeBSD-src-e7bcad327814a78ecb8d5f5545d2e3df84c67a5c.tar.gz
Vendor import of clang trunk r241361:
https://llvm.org/svn/llvm-project/cfe/trunk@241361
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp9
-rw-r--r--lib/Sema/DeclSpec.cpp12
-rw-r--r--lib/Sema/JumpDiagnostics.cpp3
-rw-r--r--lib/Sema/Sema.cpp3
-rw-r--r--lib/Sema/SemaChecking.cpp73
-rw-r--r--lib/Sema/SemaCodeComplete.cpp6
-rw-r--r--lib/Sema/SemaDecl.cpp111
-rw-r--r--lib/Sema/SemaDeclAttr.cpp33
-rw-r--r--lib/Sema/SemaDeclCXX.cpp31
-rw-r--r--lib/Sema/SemaDeclObjC.cpp40
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp10
-rw-r--r--lib/Sema/SemaExpr.cpp32
-rw-r--r--lib/Sema/SemaExprCXX.cpp6
-rw-r--r--lib/Sema/SemaExprObjC.cpp127
-rw-r--r--lib/Sema/SemaInit.cpp6
-rw-r--r--lib/Sema/SemaObjCProperty.cpp4
-rw-r--r--lib/Sema/SemaOpenMP.cpp297
-rw-r--r--lib/Sema/SemaStmt.cpp13
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp84
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp50
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp24
-rw-r--r--lib/Sema/SemaType.cpp71
-rw-r--r--lib/Sema/TreeTransform.h73
23 files changed, 861 insertions, 257 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 36030b9..f2ff48a 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -130,11 +130,10 @@ public:
return true;
// Recurse to children.
- for (ConstStmtRange SubStmts = E->children(); SubStmts; ++SubStmts)
- if (*SubStmts)
- if (const Expr *SubExpr = dyn_cast<Expr>(*SubStmts))
- if (HasMacroID(SubExpr))
- return true;
+ for (const Stmt *SubStmt : E->children())
+ if (const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt))
+ if (HasMacroID(SubExpr))
+ return true;
return false;
}
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 1e7fc75..d5c8871 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -893,6 +893,18 @@ bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
return false;
}
+bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ if (Concept_specified) {
+ DiagID = diag::ext_duplicate_declspec;
+ PrevSpec = "concept";
+ return true;
+ }
+ Concept_specified = true;
+ ConceptLoc = Loc;
+ return false;
+}
+
void DeclSpec::setProtocolQualifiers(Decl * const *Protos,
unsigned NP,
SourceLocation *ProtoLocs,
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 6b9eb2a..775fe85 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -372,13 +372,12 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
break;
}
- for (Stmt::child_range CI = S->children(); CI; ++CI) {
+ for (Stmt *SubStmt : S->children()) {
if (SkipFirstSubStmt) {
SkipFirstSubStmt = false;
continue;
}
- Stmt *SubStmt = *CI;
if (!SubStmt) continue;
// Cases, labels, and defaults aren't "scope parents". It's also
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index db1251f..18d7e9d 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -91,8 +91,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
LateTemplateParserCleanup(nullptr),
OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
- NSNumberDecl(nullptr),
+ NSNumberDecl(nullptr), NSValueDecl(nullptr),
NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
+ ValueWithBytesObjCTypeMethod(nullptr),
NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr),
NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr),
MSAsmLabelNameCounter(0),
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index f76727c..bdfff80 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1031,6 +1031,8 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
default: return false;
+ case X86::BI__builtin_cpu_supports:
+ return SemaBuiltinCpuSupports(TheCall);
case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break;
case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break;
case X86::BI__builtin_ia32_vpermil2pd:
@@ -2782,6 +2784,26 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
return false;
}
+/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
+/// This checks that the target supports __builtin_cpu_supports and
+/// that the string argument is constant and valid.
+bool Sema::SemaBuiltinCpuSupports(CallExpr *TheCall) {
+ Expr *Arg = TheCall->getArg(0);
+
+ // Check if the argument is a string literal.
+ if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
+ return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ << Arg->getSourceRange();
+
+ // Check the contents of the string.
+ StringRef Feature =
+ cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
+ if (!Context.getTargetInfo().validateCpuSupports(Feature))
+ return Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports)
+ << Arg->getSourceRange();
+ return false;
+}
+
/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
/// This checks that the target supports __builtin_longjmp and
/// that val is a constant 1.
@@ -3550,8 +3572,18 @@ public:
const char *startSpecifier, unsigned specifierLen);
bool checkForCStrMembers(const analyze_printf::ArgType &AT,
const Expr *E);
+
+ void HandleEmptyObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) override;
-};
+ void HandleInvalidObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) override;
+
+ void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
+ const char *flagsEnd,
+ const char *conversionPosition)
+ override;
+};
}
bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
@@ -3671,6 +3703,41 @@ void CheckPrintfHandler::HandleIgnoredFlag(
getSpecifierRange(ignoredFlag.getPosition(), 1)));
}
+// void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
+// bool IsStringLocation, Range StringRange,
+// ArrayRef<FixItHint> Fixit = None);
+
+void CheckPrintfHandler::HandleEmptyObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) {
+ // Warn about an empty flag.
+ EmitFormatDiagnostic(S.PDiag(diag::warn_printf_empty_objc_flag),
+ getLocationOfByte(startFlag),
+ /*IsStringLocation*/true,
+ getSpecifierRange(startFlag, flagLen));
+}
+
+void CheckPrintfHandler::HandleInvalidObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) {
+ // Warn about an invalid flag.
+ auto Range = getSpecifierRange(startFlag, flagLen);
+ StringRef flag(startFlag, flagLen);
+ EmitFormatDiagnostic(S.PDiag(diag::warn_printf_invalid_objc_flag) << flag,
+ getLocationOfByte(startFlag),
+ /*IsStringLocation*/true,
+ Range, FixItHint::CreateRemoval(Range));
+}
+
+void CheckPrintfHandler::HandleObjCFlagsWithNonObjCConversion(
+ const char *flagsStart, const char *flagsEnd, const char *conversionPosition) {
+ // Warn about using '[...]' without a '@' conversion.
+ auto Range = getSpecifierRange(flagsStart, flagsEnd - flagsStart + 1);
+ auto diag = diag::warn_printf_ObjCflags_without_ObjCConversion;
+ EmitFormatDiagnostic(S.PDiag(diag) << StringRef(conversionPosition, 1),
+ getLocationOfByte(conversionPosition),
+ /*IsStringLocation*/true,
+ Range, FixItHint::CreateRemoval(Range));
+}
+
// Determines if the specified is a C++ class or struct containing
// a member with the specified name and kind (e.g. a CXXMethodDecl named
// "c_str()").
@@ -7173,8 +7240,8 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
CC = E->getExprLoc();
BinaryOperator *BO = dyn_cast<BinaryOperator>(E);
bool IsLogicalAndOperator = BO && BO->getOpcode() == BO_LAnd;
- for (Stmt::child_range I = E->children(); I; ++I) {
- Expr *ChildExpr = dyn_cast_or_null<Expr>(*I);
+ for (Stmt *SubStmt : E->children()) {
+ Expr *ChildExpr = dyn_cast_or_null<Expr>(SubStmt);
if (!ChildExpr)
continue;
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index ebb6bbc..ff6a3ee 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1343,9 +1343,9 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
}
// Nullability
- Results.AddResult(Result("__nonnull", CCP_Type));
- Results.AddResult(Result("__null_unspecified", CCP_Type));
- Results.AddResult(Result("__nullable", CCP_Type));
+ Results.AddResult(Result("_Nonnull", CCP_Type));
+ Results.AddResult(Result("_Null_unspecified", CCP_Type));
+ Results.AddResult(Result("_Nullable", CCP_Type));
}
static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index aa006b3..6508d6f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1804,7 +1804,8 @@ static void filterNonConflictingPreviousDecls(Sema &S,
NamedDecl *decl,
LookupResult &previous){
// This is only interesting when modules are enabled.
- if (!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility)
+ if ((!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) ||
+ !S.getLangOpts().ModulesHideInternalLinkage)
return;
// Empty sets are uninteresting.
@@ -2471,17 +2472,18 @@ static void mergeParamDeclTypes(ParmVarDecl *NewParam,
if (auto Oldnullability = OldParam->getType()->getNullability(S.Context)) {
if (auto Newnullability = NewParam->getType()->getNullability(S.Context)) {
if (*Oldnullability != *Newnullability) {
- unsigned unsNewnullability = static_cast<unsigned>(*Newnullability);
- unsigned unsOldnullability = static_cast<unsigned>(*Oldnullability);
S.Diag(NewParam->getLocation(), diag::warn_mismatched_nullability_attr)
- << unsNewnullability
- << ((NewParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)
- << unsOldnullability
- << ((OldParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);
+ << DiagNullabilityKind(
+ *Newnullability,
+ ((NewParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0))
+ << DiagNullabilityKind(
+ *Oldnullability,
+ ((OldParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0));
S.Diag(OldParam->getLocation(), diag::note_previous_declaration);
}
- }
- else {
+ } else {
QualType NewT = NewParam->getType();
NewT = S.Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*Oldnullability),
@@ -3454,8 +3456,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->isThisDeclarationADefinition() == VarDecl::Definition &&
(Def = Old->getDefinition())) {
NamedDecl *Hidden = nullptr;
- if (!hasVisibleDefinition(Def, &Hidden) &&
- (New->getDescribedVarTemplate() ||
+ if (!hasVisibleDefinition(Def, &Hidden) &&
+ (New->getFormalLinkage() == InternalLinkage ||
+ New->getDescribedVarTemplate() ||
New->getNumTemplateParameterLists() ||
New->getDeclContext()->isDependentContext())) {
// The previous definition is hidden, and multiple definitions are
@@ -3577,6 +3580,23 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
}
+static unsigned GetDiagnosticTypeSpecifierID(DeclSpec::TST T) {
+ switch (T) {
+ case DeclSpec::TST_class:
+ return 0;
+ case DeclSpec::TST_struct:
+ return 1;
+ case DeclSpec::TST_interface:
+ return 2;
+ case DeclSpec::TST_union:
+ return 3;
+ case DeclSpec::TST_enum:
+ return 4;
+ default:
+ llvm_unreachable("unexpected type specifier");
+ }
+}
+
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed. It also accepts template
/// parameters to cope with template friend declarations.
@@ -3626,10 +3646,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
// and definitions of functions and variables.
if (Tag)
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
- << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
- DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
- DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
- DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4);
+ << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType());
else
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators);
// Don't emit warnings after this error.
@@ -3656,11 +3673,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
// or an explicit specialization.
// Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
- << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
- DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
- DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
- DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4)
- << SS.getRange();
+ << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
return nullptr;
}
@@ -3808,16 +3821,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
TypeSpecType == DeclSpec::TST_interface ||
TypeSpecType == DeclSpec::TST_union ||
TypeSpecType == DeclSpec::TST_enum) {
- AttributeList* attrs = DS.getAttributes().getList();
- while (attrs) {
+ for (AttributeList* attrs = DS.getAttributes().getList(); attrs;
+ attrs = attrs->getNext())
Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored)
- << attrs->getName()
- << (TypeSpecType == DeclSpec::TST_class ? 0 :
- TypeSpecType == DeclSpec::TST_struct ? 1 :
- TypeSpecType == DeclSpec::TST_union ? 2 :
- TypeSpecType == DeclSpec::TST_interface ? 3 : 4);
- attrs = attrs->getNext();
- }
+ << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType);
}
}
@@ -5518,6 +5525,19 @@ bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
return true;
}
+/// \brief Returns true if given declaration is TU-scoped and externally
+/// visible.
+static bool isDeclTUScopedExternallyVisible(const Decl *D) {
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ return (FD->getDeclContext()->isTranslationUnit() || FD->isExternC()) &&
+ FD->hasExternalFormalLinkage();
+ else if (auto *VD = dyn_cast<VarDecl>(D))
+ return (VD->getDeclContext()->isTranslationUnit() || VD->isExternC()) &&
+ VD->hasExternalFormalLinkage();
+
+ llvm_unreachable("Unknown type of decl!");
+}
+
NamedDecl *
Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -5942,7 +5962,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
Context, Label, 0));
- } else if (!ExtnameUndeclaredIdentifiers.empty()) {
+ } else if (!ExtnameUndeclaredIdentifiers.empty() &&
+ isDeclTUScopedExternallyVisible(NewVD)) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
@@ -7181,6 +7202,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
dyn_cast<CXXRecordDecl>(NewFD->getDeclContext())) {
if (Parent->isInterface() && cast<CXXMethodDecl>(NewFD)->isUserProvided())
NewFD->setPure(true);
+
+ // C++ [class.union]p2
+ // A union can have member functions, but not virtual functions.
+ if (isVirtual && Parent->isUnion())
+ Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_in_union);
}
SetNestedNameSpecifier(NewFD, D);
@@ -7464,7 +7490,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
SE->getString(), 0));
- } else if (!ExtnameUndeclaredIdentifiers.empty()) {
+ } else if (!ExtnameUndeclaredIdentifiers.empty() &&
+ isDeclTUScopedExternallyVisible(NewFD)) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
@@ -8769,18 +8796,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
- // With declarators parsed the way they are, the parser cannot
- // distinguish between a normal initializer and a pure-specifier.
- // Thus this grotesque test.
- IntegerLiteral *IL;
- if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 &&
- Context.getCanonicalType(IL->getType()) == Context.IntTy)
- CheckPureMethod(Method, Init->getSourceRange());
- else {
- Diag(Method->getLocation(), diag::err_member_function_initialization)
- << Method->getDeclName() << Init->getSourceRange();
- Method->setInvalidDecl();
- }
+ // Pure-specifiers are handled in ActOnPureSpecifier.
+ Diag(Method->getLocation(), diag::err_member_function_initialization)
+ << Method->getDeclName() << Init->getSourceRange();
+ Method->setInvalidDecl();
return;
}
@@ -8943,7 +8962,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if ((Def = VDecl->getDefinition()) && Def != VDecl) {
NamedDecl *Hidden = nullptr;
if (!hasVisibleDefinition(Def, &Hidden) &&
- (VDecl->getDescribedVarTemplate() ||
+ (VDecl->getFormalLinkage() == InternalLinkage ||
+ VDecl->getDescribedVarTemplate() ||
VDecl->getNumTemplateParameterLists() ||
VDecl->getDeclContext()->isDependentContext())) {
// The previous definition is hidden, and multiple definitions are
@@ -10364,7 +10384,8 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
// in this case? That may be necessary for functions that return local types
// through a deduced return type, or instantiate templates with local types.
if (!hasVisibleDefinition(Definition) &&
- (Definition->isInlineSpecified() ||
+ (Definition->getFormalLinkage() == InternalLinkage ||
+ Definition->isInlined() ||
Definition->getDescribedFunctionTemplate() ||
Definition->getNumTemplateParameterLists()))
return;
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 43790c2..b8d0830 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -3990,6 +3991,34 @@ static void handleObjCRuntimeName(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+// when a user wants to use objc_boxable with a union or struct
+// but she doesn't have access to the declaration (legacy/third-party code)
+// then she can 'enable' this feature via trick with a typedef
+// e.g.:
+// typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
+static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &Attr) {
+ bool notify = false;
+
+ RecordDecl *RD = dyn_cast<RecordDecl>(D);
+ if (RD && RD->getDefinition()) {
+ RD = RD->getDefinition();
+ notify = true;
+ }
+
+ if (RD) {
+ ObjCBoxableAttr *BoxableAttr = ::new (S.Context)
+ ObjCBoxableAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex());
+ RD->addAttr(BoxableAttr);
+ if (notify) {
+ // we need to notify ASTReader/ASTWriter about
+ // modification of existing declaration
+ if (ASTMutationListener *L = S.getASTMutationListener())
+ L->AddedAttributeToRecord(BoxableAttr, RD);
+ }
+ }
+}
+
static void handleObjCOwnershipAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (hasDeclarator(D)) return;
@@ -4758,6 +4787,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ObjCRuntimeName:
handleObjCRuntimeName(S, D, Attr);
break;
+
+ case AttributeList::AT_ObjCBoxable:
+ handleObjCBoxable(S, D, Attr);
+ break;
case AttributeList::AT_CFAuditedTransfer:
handleCFAuditedTransferAttr(S, D, Attr);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 7ed9bfc..0d7cbf4 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -73,8 +73,8 @@ namespace {
/// VisitExpr - Visit all of the children of this expression.
bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
bool IsInvalid = false;
- for (Stmt::child_range I = Node->children(); I; ++I)
- IsInvalid |= Visit(*I);
+ for (Stmt *SubStmt : Node->children())
+ IsInvalid |= Visit(SubStmt);
return IsInvalid;
}
@@ -1091,9 +1091,9 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
break;
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getLocStart();
- for (Stmt::child_range Children = S->children(); Children; ++Children)
- if (*Children &&
- !CheckConstexprFunctionStmt(SemaRef, Dcl, *Children, ReturnStmts,
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt &&
+ !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
Cxx1yLoc))
return false;
return true;
@@ -1106,9 +1106,9 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
// mutation, we can reasonably allow them in C++11 as an extension.
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getLocStart();
- for (Stmt::child_range Children = S->children(); Children; ++Children)
- if (*Children &&
- !CheckConstexprFunctionStmt(SemaRef, Dcl, *Children, ReturnStmts,
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt &&
+ !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
Cxx1yLoc))
return false;
return true;
@@ -2186,9 +2186,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
assert(Member && "HandleField never returns null");
}
} else {
- assert(InitStyle == ICIS_NoInit ||
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static);
-
Member = HandleDeclarator(S, D, TemplateParameterLists);
if (!Member)
return nullptr;
@@ -12890,8 +12887,7 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
}
static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
- for (Stmt::child_range CI = S->children(); CI; ++CI) {
- Stmt *SubStmt = *CI;
+ for (Stmt *SubStmt : S->children()) {
if (!SubStmt)
continue;
if (isa<ReturnStmt>(SubStmt))
@@ -13060,6 +13056,15 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
return true;
}
+void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
+ if (D->getFriendObjectKind())
+ Diag(D->getLocation(), diag::err_pure_friend);
+ else if (auto *M = dyn_cast<CXXMethodDecl>(D))
+ CheckPureMethod(M, ZeroLoc);
+ else
+ Diag(D->getLocation(), diag::err_illegal_initializer);
+}
+
/// \brief Determine whether the given declaration is a static data member.
static bool isStaticDataMember(const Decl *D) {
if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 543566f..d0b2998 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1400,16 +1400,20 @@ static bool CheckMethodOverrideReturn(Sema &S,
!S.Context.hasSameNullabilityTypeQualifier(MethodImpl->getReturnType(),
MethodDecl->getReturnType(),
false)) {
- unsigned unsNullabilityMethodImpl =
- static_cast<unsigned>(*MethodImpl->getReturnType()->getNullability(S.Context));
- unsigned unsNullabilityMethodDecl =
- static_cast<unsigned>(*MethodDecl->getReturnType()->getNullability(S.Context));
+ auto nullabilityMethodImpl =
+ *MethodImpl->getReturnType()->getNullability(S.Context);
+ auto nullabilityMethodDecl =
+ *MethodDecl->getReturnType()->getNullability(S.Context);
S.Diag(MethodImpl->getLocation(),
diag::warn_conflicting_nullability_attr_overriding_ret_types)
- << unsNullabilityMethodImpl
- << ((MethodImpl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)
- << unsNullabilityMethodDecl
- << ((MethodDecl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);
+ << DiagNullabilityKind(
+ nullabilityMethodImpl,
+ ((MethodImpl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0))
+ << DiagNullabilityKind(
+ nullabilityMethodDecl,
+ ((MethodDecl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0));
S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
}
@@ -1486,15 +1490,17 @@ static bool CheckMethodOverrideParam(Sema &S,
if (Warn && IsOverridingMode &&
!isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&
!S.Context.hasSameNullabilityTypeQualifier(ImplTy, IfaceTy, true)) {
- unsigned unsImplTy = static_cast<unsigned>(*ImplTy->getNullability(S.Context));
- unsigned unsIfaceTy = static_cast<unsigned>(*IfaceTy->getNullability(S.Context));
S.Diag(ImplVar->getLocation(),
diag::warn_conflicting_nullability_attr_overriding_param_types)
- << unsImplTy
- << ((ImplVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)
- << unsIfaceTy
- << ((IfaceVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);
- S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);
+ << DiagNullabilityKind(
+ *ImplTy->getNullability(S.Context),
+ ((ImplVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0))
+ << DiagNullabilityKind(
+ *IfaceTy->getNullability(S.Context),
+ ((IfaceVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ != 0));
+ S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);
}
if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
return true;
@@ -3184,8 +3190,8 @@ static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,
// Complain about mismatched nullability.
S.Diag(loc, diag::err_nullability_conflicting)
- << static_cast<unsigned>(*nullability) << usesCSKeyword
- << static_cast<unsigned>(*prevNullability) << prevUsesCSKeyword;
+ << DiagNullabilityKind(*nullability, usesCSKeyword)
+ << DiagNullabilityKind(*prevNullability, prevUsesCSKeyword);
return type;
}
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index f3bcf76..2e3e63e 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -837,11 +837,13 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
New->getLocation());
}
-static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
- Expr *E = const_cast<Expr*>(CE);
+static CanThrowResult canSubExprsThrow(Sema &S, const Expr *E) {
CanThrowResult R = CT_Cannot;
- for (Expr::child_range I = E->children(); I && R != CT_Can; ++I)
- R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I)));
+ for (const Stmt *SubStmt : E->children()) {
+ R = mergeCanThrow(R, S.canThrow(cast<Expr>(SubStmt)));
+ if (R == CT_Can)
+ break;
+ }
return R;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index b0bc231..c023c85 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3689,7 +3689,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
// C11 6.5.3.4/3, C++11 [expr.alignof]p3:
// When alignof or _Alignof is applied to an array type, the result
// is the alignment of the element type.
- if (ExprKind == UETT_AlignOf)
+ if (ExprKind == UETT_AlignOf || ExprKind == UETT_OpenMPRequiredSimdAlign)
ExprType = Context.getBaseElementType(ExprType);
if (ExprKind == UETT_VecStep)
@@ -3824,6 +3824,9 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
isInvalid = CheckAlignOfExpr(*this, E);
} else if (ExprKind == UETT_VecStep) {
isInvalid = CheckVecStepExpr(E);
+ } else if (ExprKind == UETT_OpenMPRequiredSimdAlign) {
+ Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
+ isInvalid = true;
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
isInvalid = true;
@@ -4314,7 +4317,6 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
SourceLocation RParenLoc,
bool IsExecConfig) {
// Bail out early if calling a builtin with custom typechecking.
- // We don't need to do this in the
if (FDecl)
if (unsigned ID = FDecl->getBuiltinID())
if (Context.BuiltinInfo.hasCustomTypechecking(ID))
@@ -4938,6 +4940,17 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
TheCall = new (Context) CallExpr(Context, Fn, Args, Context.BoolTy,
VK_RValue, RParenLoc);
+ if (!getLangOpts().CPlusPlus) {
+ // C cannot always handle TypoExpr nodes in builtin calls and direct
+ // function calls as their argument checking don't necessarily handle
+ // dependent types properly, so make sure any TypoExprs have been
+ // dealt with.
+ ExprResult Result = CorrectDelayedTyposInExpr(TheCall);
+ if (!Result.isUsable()) return ExprError();
+ TheCall = dyn_cast<CallExpr>(Result.get());
+ if (!TheCall) return Result;
+ }
+
// Bail out early if calling a builtin with custom typechecking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
@@ -12742,6 +12755,7 @@ bool Sema::tryCaptureVariable(
bool Nested = false;
bool Explicit = (Kind != TryCapture_Implicit);
unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
+ unsigned OpenMPLevel = 0;
do {
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
@@ -12768,6 +12782,20 @@ bool Sema::tryCaptureVariable(
if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
DeclRefType))
break;
+ if (getLangOpts().OpenMP) {
+ if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+ // OpenMP private variables should not be captured in outer scope, so
+ // just break here.
+ if (RSI->CapRegionKind == CR_OpenMP) {
+ if (isOpenMPPrivateVar(Var, OpenMPLevel)) {
+ Nested = true;
+ CaptureType = Context.getLValueReferenceType(DeclRefType);
+ break;
+ }
+ ++OpenMPLevel;
+ }
+ }
+ }
// If we are instantiating a generic lambda call operator body,
// we do not want to capture new variables. What was captured
// during either a lambdas transformation or initial parsing
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 6c839f3..6608d7c 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -6506,6 +6506,11 @@ public:
// with the same edit length that pass all the checks and filters.
// TODO: Properly handle various permutations of possible corrections when
// there is more than one potentially ambiguous typo correction.
+ // Also, disable typo correction while attempting the transform when
+ // handling potentially ambiguous typo corrections as any new TypoExprs will
+ // have been introduced by the application of one of the correction
+ // candidates and add little to no value if corrected.
+ SemaRef.DisableTypoCorrection = true;
while (!AmbiguousTypoExprs.empty()) {
auto TE = AmbiguousTypoExprs.back();
auto Cached = TransformCache[TE];
@@ -6522,6 +6527,7 @@ public:
State.Consumer->restoreSavedPosition();
TransformCache[TE] = Cached;
}
+ SemaRef.DisableTypoCorrection = false;
// Ensure that all of the TypoExprs within the current Expr have been found.
if (!Res.isUsable())
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 9947fad..c52b6f5 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -563,7 +563,6 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
// Look for the appropriate method within NSNumber.
BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
BoxedType = NSNumberPointer;
-
} else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
if (!ET->getDecl()->isComplete()) {
Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type)
@@ -574,6 +573,109 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(),
ET->getDecl()->getIntegerType());
BoxedType = NSNumberPointer;
+ } else if (ValueType->isObjCBoxableRecordType()) {
+ // Support for structure types, that marked as objc_boxable
+ // struct __attribute__((objc_boxable)) s { ... };
+
+ // Look up the NSValue class, if we haven't done so already. It's cached
+ // in the Sema instance.
+ if (!NSValueDecl) {
+ IdentifierInfo *NSValueId =
+ NSAPIObj->getNSClassId(NSAPI::ClassId_NSValue);
+ NamedDecl *IF = LookupSingleName(TUScope, NSValueId,
+ SR.getBegin(), Sema::LookupOrdinaryName);
+ NSValueDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (!NSValueDecl) {
+ if (getLangOpts().DebuggerObjCLiteral) {
+ // Create a stub definition of NSValue.
+ DeclContext *TU = Context.getTranslationUnitDecl();
+ NSValueDecl = ObjCInterfaceDecl::Create(Context, TU,
+ SourceLocation(), NSValueId,
+ nullptr, SourceLocation());
+ } else {
+ // Otherwise, require a declaration of NSValue.
+ Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
+ return ExprError();
+ }
+ } else if (!NSValueDecl->hasDefinition()) {
+ Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
+ return ExprError();
+ }
+
+ // generate the pointer to NSValue type.
+ QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);
+ NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);
+ }
+
+ if (!ValueWithBytesObjCTypeMethod) {
+ IdentifierInfo *II[] = {
+ &Context.Idents.get("valueWithBytes"),
+ &Context.Idents.get("objCType")
+ };
+ Selector ValueWithBytesObjCType = Context.Selectors.getSelector(2, II);
+
+ // Look for the appropriate method within NSValue.
+ BoxingMethod = NSValueDecl->lookupClassMethod(ValueWithBytesObjCType);
+ if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
+ // Debugger needs to work even if NSValue hasn't been defined.
+ TypeSourceInfo *ReturnTInfo = nullptr;
+ ObjCMethodDecl *M = ObjCMethodDecl::Create(
+ Context,
+ SourceLocation(),
+ SourceLocation(),
+ ValueWithBytesObjCType,
+ NSValuePointer,
+ ReturnTInfo,
+ NSValueDecl,
+ /*isInstance=*/false,
+ /*isVariadic=*/false,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false,
+ ObjCMethodDecl::Required,
+ /*HasRelatedResultType=*/false);
+
+ SmallVector<ParmVarDecl *, 2> Params;
+
+ ParmVarDecl *bytes =
+ ParmVarDecl::Create(Context, M,
+ SourceLocation(), SourceLocation(),
+ &Context.Idents.get("bytes"),
+ Context.VoidPtrTy.withConst(),
+ /*TInfo=*/nullptr,
+ SC_None, nullptr);
+ Params.push_back(bytes);
+
+ QualType ConstCharType = Context.CharTy.withConst();
+ ParmVarDecl *type =
+ ParmVarDecl::Create(Context, M,
+ SourceLocation(), SourceLocation(),
+ &Context.Idents.get("type"),
+ Context.getPointerType(ConstCharType),
+ /*TInfo=*/nullptr,
+ SC_None, nullptr);
+ Params.push_back(type);
+
+ M->setMethodParams(Context, Params, None);
+ BoxingMethod = M;
+ }
+
+ if (!validateBoxingMethod(*this, SR.getBegin(), NSValueDecl,
+ ValueWithBytesObjCType, BoxingMethod))
+ return ExprError();
+
+ ValueWithBytesObjCTypeMethod = BoxingMethod;
+ }
+
+ if (!ValueType.isTriviallyCopyableType(Context)) {
+ Diag(SR.getBegin(),
+ diag::err_objc_non_trivially_copyable_boxed_expression_type)
+ << ValueType << ValueExpr->getSourceRange();
+ return ExprError();
+ }
+
+ BoxingMethod = ValueWithBytesObjCTypeMethod;
+ BoxedType = NSValuePointer;
}
if (!BoxingMethod) {
@@ -582,13 +684,22 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
return ExprError();
}
- // Convert the expression to the type that the parameter requires.
- ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];
- InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
- ParamDecl);
- ExprResult ConvertedValueExpr = PerformCopyInitialization(Entity,
- SourceLocation(),
- ValueExpr);
+ DiagnoseUseOfDecl(BoxingMethod, SR.getBegin());
+
+ ExprResult ConvertedValueExpr;
+ if (ValueType->isObjCBoxableRecordType()) {
+ InitializedEntity IE = InitializedEntity::InitializeTemporary(ValueType);
+ ConvertedValueExpr = PerformCopyInitialization(IE, ValueExpr->getExprLoc(),
+ ValueExpr);
+ } else {
+ // Convert the expression to the type that the parameter requires.
+ ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];
+ InitializedEntity IE = InitializedEntity::InitializeParameter(Context,
+ ParamDecl);
+ ConvertedValueExpr = PerformCopyInitialization(IE, SourceLocation(),
+ ValueExpr);
+ }
+
if (ConvertedValueExpr.isInvalid())
return ExprError();
ValueExpr = ConvertedValueExpr.get();
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 821d7f6..f0f7cb9 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -5088,10 +5088,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
}
InitializationSequence::~InitializationSequence() {
- for (SmallVectorImpl<Step>::iterator Step = Steps.begin(),
- StepEnd = Steps.end();
- Step != StepEnd; ++Step)
- Step->Destroy();
+ for (auto &S : Steps)
+ S.Destroy();
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 87fb5b6..0f88abc 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -1758,7 +1758,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
}
}
-void Sema::diagnoseNullResettableSynthesizedSetters(ObjCImplDecl *impDecl) {
+void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) {
for (const auto *propertyImpl : impDecl->property_impls()) {
const auto *property = propertyImpl->getPropertyDecl();
@@ -2025,7 +2025,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
if (property->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_null_resettable) {
QualType modifiedTy = resultTy;
- if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
+ if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
if (*nullability == NullabilityKind::Unspecified)
resultTy = Context.getAttributedType(AttributedType::attr_nonnull,
modifiedTy, modifiedTy);
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index e609fcf..867cb9f 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -95,19 +95,20 @@ private:
Scope *CurScope;
SourceLocation ConstructLoc;
bool OrderedRegion;
+ bool NowaitRegion;
unsigned CollapseNumber;
SourceLocation InnerTeamsRegionLoc;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
: SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
- ConstructLoc(Loc), OrderedRegion(false), CollapseNumber(1),
- InnerTeamsRegionLoc() {}
+ ConstructLoc(Loc), OrderedRegion(false), NowaitRegion(false),
+ CollapseNumber(1), InnerTeamsRegionLoc() {}
SharingMapTy()
: SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
- ConstructLoc(), OrderedRegion(false), CollapseNumber(1),
- InnerTeamsRegionLoc() {}
+ ConstructLoc(), OrderedRegion(false), NowaitRegion(false),
+ CollapseNumber(1), InnerTeamsRegionLoc() {}
};
typedef SmallVector<SharingMapTy, 64> StackTy;
@@ -116,7 +117,7 @@ private:
StackTy Stack;
/// \brief true, if check for DSA must be from parent directive, false, if
/// from current directive.
- bool FromParent;
+ OpenMPClauseKind ClauseKindMode;
Sema &SemaRef;
typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
@@ -127,10 +128,11 @@ private:
bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
public:
- explicit DSAStackTy(Sema &S) : Stack(1), FromParent(false), SemaRef(S) {}
+ explicit DSAStackTy(Sema &S)
+ : Stack(1), ClauseKindMode(OMPC_unknown), SemaRef(S) {}
- bool isFromParent() const { return FromParent; }
- void setFromParent(bool Flag) { FromParent = Flag; }
+ bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
+ void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
Scope *CurScope, SourceLocation Loc) {
@@ -175,6 +177,12 @@ public:
DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
DirectivesPredicate DPred,
bool FromParent);
+ /// \brief Checks if the specified variables has explicit data-sharing
+ /// attributes which match specified \a CPred predicate at the specified
+ /// OpenMP region.
+ bool hasExplicitDSA(VarDecl *D,
+ const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
+ unsigned Level);
/// \brief Finds a directive which matches specified \a DPred predicate.
template <class NamedDirectivesPredicate>
bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent);
@@ -225,6 +233,17 @@ public:
return Stack[Stack.size() - 2].OrderedRegion;
return false;
}
+ /// \brief Marks current region as nowait (it has a 'nowait' clause).
+ void setNowaitRegion(bool IsNowait = true) {
+ Stack.back().NowaitRegion = IsNowait;
+ }
+ /// \brief Returns true, if parent region is nowait (has associated
+ /// 'nowait' clause), false - otherwise.
+ bool isParentNowaitRegion() const {
+ if (Stack.size() > 2)
+ return Stack[Stack.size() - 2].NowaitRegion;
+ return false;
+ }
/// \brief Set collapse value for the region.
void setCollapseNumber(unsigned Val) { Stack.back().CollapseNumber = Val; }
@@ -589,6 +608,23 @@ DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
return DSAVarData();
}
+bool DSAStackTy::hasExplicitDSA(
+ VarDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
+ unsigned Level) {
+ if (CPred(ClauseKindMode))
+ return true;
+ if (isClauseParsingMode())
+ ++Level;
+ D = D->getCanonicalDecl();
+ auto StartI = Stack.rbegin();
+ auto EndI = std::prev(Stack.rend());
+ if (std::distance(StartI, EndI) <= (int)Level)
+ return false;
+ std::advance(StartI, Level);
+ return (StartI->SharingMap.count(D) > 0) && StartI->SharingMap[D].RefExpr &&
+ CPred(StartI->SharingMap[D].Attributes);
+}
+
template <class NamedDirectivesPredicate>
bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {
auto StartI = std::next(Stack.rbegin());
@@ -617,16 +653,22 @@ bool Sema::IsOpenMPCapturedVar(VarDecl *VD) {
(VD->hasLocalStorage() &&
isParallelOrTaskRegion(DSAStack->getCurrentDirective())))
return true;
- auto DVarPrivate = DSAStack->getTopDSA(VD, DSAStack->isFromParent());
+ auto DVarPrivate = DSAStack->getTopDSA(VD, DSAStack->isClauseParsingMode());
if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind))
return true;
DVarPrivate = DSAStack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(),
- DSAStack->isFromParent());
+ DSAStack->isClauseParsingMode());
return DVarPrivate.CKind != OMPC_unknown;
}
return false;
}
+bool Sema::isOpenMPPrivateVar(VarDecl *VD, unsigned Level) {
+ assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ return DSAStack->hasExplicitDSA(
+ VD, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level);
+}
+
void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
@@ -636,12 +678,12 @@ void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
PushExpressionEvaluationContext(PotentiallyEvaluated);
}
-void Sema::StartOpenMPClauses() {
- DSAStack->setFromParent(/*Flag=*/true);
+void Sema::StartOpenMPClause(OpenMPClauseKind K) {
+ DSAStack->setClauseParsingMode(K);
}
-void Sema::EndOpenMPClauses() {
- DSAStack->setFromParent(/*Flag=*/false);
+void Sema::EndOpenMPClause() {
+ DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
}
void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
@@ -1282,6 +1324,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
+ case OMPD_cancellation_point:
+ case OMPD_cancel:
case OMPD_flush:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
@@ -1322,6 +1366,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
OpenMPDirectiveKind CurrentRegion,
const DeclarationNameInfo &CurrentName,
+ OpenMPDirectiveKind CancelRegion,
SourceLocation StartLoc) {
// Allowed nesting of constructs
// +------------------+-----------------+------------------------------------+
@@ -1349,6 +1394,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel | atomic | * |
// | parallel | target | * |
// | parallel | teams | + |
+ // | parallel | cancellation | |
+ // | | point | ! |
+ // | parallel | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
@@ -1372,6 +1420,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for | atomic | * |
// | for | target | * |
// | for | teams | + |
+ // | for | cancellation | |
+ // | | point | ! |
+ // | for | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | master | parallel | * |
// | master | for | + |
@@ -1395,6 +1446,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | master | atomic | * |
// | master | target | * |
// | master | teams | + |
+ // | master | cancellation | |
+ // | | point | |
+ // | master | cancel | |
// +------------------+-----------------+------------------------------------+
// | critical | parallel | * |
// | critical | for | + |
@@ -1417,6 +1471,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | critical | atomic | * |
// | critical | target | * |
// | critical | teams | + |
+ // | critical | cancellation | |
+ // | | point | |
+ // | critical | cancel | |
// +------------------+-----------------+------------------------------------+
// | simd | parallel | |
// | simd | for | |
@@ -1440,6 +1497,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | simd | atomic | |
// | simd | target | |
// | simd | teams | |
+ // | simd | cancellation | |
+ // | | point | |
+ // | simd | cancel | |
// +------------------+-----------------+------------------------------------+
// | for simd | parallel | |
// | for simd | for | |
@@ -1463,6 +1523,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for simd | atomic | |
// | for simd | target | |
// | for simd | teams | |
+ // | for simd | cancellation | |
+ // | | point | |
+ // | for simd | cancel | |
// +------------------+-----------------+------------------------------------+
// | parallel for simd| parallel | |
// | parallel for simd| for | |
@@ -1486,6 +1549,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for simd| atomic | |
// | parallel for simd| target | |
// | parallel for simd| teams | |
+ // | parallel for simd| cancellation | |
+ // | | point | |
+ // | parallel for simd| cancel | |
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
@@ -1509,6 +1575,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | sections | atomic | * |
// | sections | target | * |
// | sections | teams | + |
+ // | sections | cancellation | |
+ // | | point | ! |
+ // | sections | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
@@ -1532,6 +1601,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | section | atomic | * |
// | section | target | * |
// | section | teams | + |
+ // | section | cancellation | |
+ // | | point | ! |
+ // | section | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
@@ -1555,6 +1627,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | single | atomic | * |
// | single | target | * |
// | single | teams | + |
+ // | single | cancellation | |
+ // | | point | |
+ // | single | cancel | |
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
@@ -1578,6 +1653,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for | atomic | * |
// | parallel for | target | * |
// | parallel for | teams | + |
+ // | parallel for | cancellation | |
+ // | | point | ! |
+ // | parallel for | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
@@ -1601,6 +1679,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel sections| atomic | * |
// | parallel sections| target | * |
// | parallel sections| teams | + |
+ // | parallel sections| cancellation | |
+ // | | point | ! |
+ // | parallel sections| cancel | ! |
// +------------------+-----------------+------------------------------------+
// | task | parallel | * |
// | task | for | + |
@@ -1624,6 +1705,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | task | atomic | * |
// | task | target | * |
// | task | teams | + |
+ // | task | cancellation | |
+ // | | point | ! |
+ // | task | cancel | ! |
// +------------------+-----------------+------------------------------------+
// | ordered | parallel | * |
// | ordered | for | + |
@@ -1647,6 +1731,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | ordered | atomic | * |
// | ordered | target | * |
// | ordered | teams | + |
+ // | ordered | cancellation | |
+ // | | point | |
+ // | ordered | cancel | |
// +------------------+-----------------+------------------------------------+
// | atomic | parallel | |
// | atomic | for | |
@@ -1670,6 +1757,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | atomic | atomic | |
// | atomic | target | |
// | atomic | teams | |
+ // | atomic | cancellation | |
+ // | | point | |
+ // | atomic | cancel | |
// +------------------+-----------------+------------------------------------+
// | target | parallel | * |
// | target | for | * |
@@ -1693,6 +1783,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | target | atomic | * |
// | target | target | * |
// | target | teams | * |
+ // | target | cancellation | |
+ // | | point | |
+ // | target | cancel | |
// +------------------+-----------------+------------------------------------+
// | teams | parallel | * |
// | teams | for | + |
@@ -1710,12 +1803,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | teams | taskyield | + |
// | teams | barrier | + |
// | teams | taskwait | + |
- // | teams | taskgroup | + |
+ // | teams | taskgroup | + |
// | teams | flush | + |
// | teams | ordered | + |
// | teams | atomic | + |
// | teams | target | + |
// | teams | teams | + |
+ // | teams | cancellation | |
+ // | | point | |
+ // | teams | cancel | |
// +------------------+-----------------+------------------------------------+
if (Stack->getCurScope()) {
auto ParentRegion = Stack->getParentDirective();
@@ -1757,7 +1853,26 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// called from OpenMP regions with the required preconditions).
if (ParentRegion == OMPD_unknown)
return false;
- if (CurrentRegion == OMPD_master) {
+ if (CurrentRegion == OMPD_cancellation_point ||
+ CurrentRegion == OMPD_cancel) {
+ // OpenMP [2.16, Nesting of Regions]
+ // A cancellation point construct for which construct-type-clause is
+ // taskgroup must be nested inside a task construct. A cancellation
+ // point construct for which construct-type-clause is not taskgroup must
+ // be closely nested inside an OpenMP construct that matches the type
+ // specified in construct-type-clause.
+ // A cancel construct for which construct-type-clause is taskgroup must be
+ // nested inside a task construct. A cancel construct for which
+ // construct-type-clause is not taskgroup must be closely nested inside an
+ // OpenMP construct that matches the type specified in
+ // construct-type-clause.
+ NestingProhibited =
+ !((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) ||
+ (CancelRegion == OMPD_for && ParentRegion == OMPD_for) ||
+ (CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) ||
+ (CancelRegion == OMPD_sections &&
+ (ParentRegion == OMPD_section || ParentRegion == OMPD_sections)));
+ } else if (CurrentRegion == OMPD_master) {
// OpenMP [2.16, Nesting of Regions]
// A master region may not be closely nested inside a worksharing,
// atomic, or explicit task region.
@@ -1847,14 +1962,13 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
return false;
}
-StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
- const DeclarationNameInfo &DirName,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
+StmtResult Sema::ActOnOpenMPExecutableDirective(
+ OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
+ OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
StmtResult Res = StmtError();
- if (CheckNestingOfRegions(*this, DSAStack, Kind, DirName, StartLoc))
+ if (CheckNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
+ StartLoc))
return StmtError();
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
@@ -1988,6 +2102,20 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
break;
+ case OMPD_cancellation_point:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp cancellation point' directive");
+ assert(AStmt == nullptr && "No associated statement allowed for 'omp "
+ "cancellation point' directive");
+ Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
+ break;
+ case OMPD_cancel:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp cancel' directive");
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp cancel' directive");
+ Res = ActOnOpenMPCancelDirective(StartLoc, EndLoc, CancelRegion);
+ break;
case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
@@ -3216,8 +3344,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
// All associated statements must be '#pragma omp section' except for
// the first one.
- for (++S; S; ++S) {
- auto SectionStmt = *S;
+ for (Stmt *SectionStmt : ++S) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
Diag(SectionStmt->getLocStart(),
@@ -3375,8 +3502,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
// All associated statements must be '#pragma omp section' except for
// the first one.
- for (++S; S; ++S) {
- auto SectionStmt = *S;
+ for (Stmt *SectionStmt : ++S) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
Diag(SectionStmt->getLocStart(),
@@ -4174,6 +4300,48 @@ StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
+StmtResult
+Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion) {
+ if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for &&
+ CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) {
+ Diag(StartLoc, diag::err_omp_wrong_cancel_region)
+ << getOpenMPDirectiveName(CancelRegion);
+ return StmtError();
+ }
+ if (DSAStack->isParentNowaitRegion()) {
+ Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
+ return StmtError();
+ }
+ if (DSAStack->isParentOrderedRegion()) {
+ Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
+ return StmtError();
+ }
+ return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
+ CancelRegion);
+}
+
+StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion) {
+ if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for &&
+ CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) {
+ Diag(StartLoc, diag::err_omp_wrong_cancel_region)
+ << getOpenMPDirectiveName(CancelRegion);
+ return StmtError();
+ }
+ if (DSAStack->isParentNowaitRegion()) {
+ Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
+ return StmtError();
+ }
+ if (DSAStack->isParentOrderedRegion()) {
+ Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
+ return StmtError();
+ }
+ return OMPCancelDirective::Create(Context, StartLoc, EndLoc, CancelRegion);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -4218,6 +4386,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -4432,6 +4601,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -4552,6 +4722,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -4674,6 +4845,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_proc_bind:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -4688,6 +4860,7 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
SourceLocation EndLoc) {
+ DSAStack->setNowaitRegion();
return new (Context) OMPNowaitClause(StartLoc, EndLoc);
}
@@ -4730,7 +4903,8 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
- const DeclarationNameInfo &ReductionId) {
+ const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_private:
@@ -4766,6 +4940,10 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_flush:
Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_depend:
+ Res = ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList, StartLoc,
+ LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -6316,3 +6494,66 @@ OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
}
+OMPClause *
+Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc) {
+ if (DepKind == OMPC_DEPEND_unknown) {
+ std::string Values;
+ std::string Sep(", ");
+ for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) {
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i);
+ Values += "'";
+ switch (i) {
+ case OMPC_DEPEND_unknown - 2:
+ Values += " or ";
+ break;
+ case OMPC_DEPEND_unknown - 1:
+ break;
+ default:
+ Values += Sep;
+ break;
+ }
+ }
+ Diag(DepLoc, diag::err_omp_unexpected_clause_value)
+ << Values << getOpenMPClauseName(OMPC_depend);
+ return nullptr;
+ }
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.11.1.1, Restrictions, p.3]
+ // A variable that is part of another variable (such as a field of a
+ // structure) but is not an array element or an array section cannot appear
+ // in a depend clause.
+ auto *SimpleExpr = RefExpr->IgnoreParenCasts();
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (!ASE && !DE) ||
+ (DE && !isa<VarDecl>(DE->getDecl())) ||
+ (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
+ !ASE->getBase()->getType()->isArrayType())) {
+ Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
+
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind,
+ DepLoc, ColonLoc, Vars);
+}
+
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 50e4345..6fca974 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -495,6 +495,7 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
+ CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc);
if (CondResult.isInvalid())
return StmtError();
}
@@ -649,12 +650,10 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
if (CondResult.isInvalid()) return StmtError();
Cond = CondResult.get();
- if (!CondVar) {
- CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);
- if (CondResult.isInvalid())
- return StmtError();
- Cond = CondResult.get();
- }
+ CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);
+ if (CondResult.isInvalid())
+ return StmtError();
+ Cond = CondResult.get();
getCurFunction()->setHasBranchIntoScope();
@@ -1229,6 +1228,7 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);
+ CondResult = ActOnFinishFullExpr(CondResult.get(), WhileLoc);
if (CondResult.isInvalid())
return StmtError();
}
@@ -1634,6 +1634,7 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
if (secondVar) {
ConditionVar = cast<VarDecl>(secondVar);
SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);
+ SecondResult = ActOnFinishFullExpr(SecondResult.get(), ForLoc);
if (SecondResult.isInvalid())
return StmtError();
}
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 6f676ad..ae8157e 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -3190,6 +3190,40 @@ static bool
hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate,
QualType T);
+static Sema::TemplateDeductionResult DeduceTemplateArgumentByListElement(
+ Sema &S, TemplateParameterList *TemplateParams, QualType ParamType,
+ Expr *Arg, TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF);
+
+/// \brief Attempt template argument deduction from an initializer list
+/// deemed to be an argument in a function call.
+static bool
+DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams,
+ QualType AdjustedParamType, InitListExpr *ILE,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned TDF, Sema::TemplateDeductionResult &Result) {
+ // If the argument is an initializer list then the parameter is an undeduced
+ // context, unless the parameter type is (reference to cv)
+ // std::initializer_list<P'>, in which case deduction is done for each element
+ // of the initializer list as-if it were an argument in a function call, and
+ // the result is the deduced type if it's the same for all elements.
+ QualType X;
+ if (!S.isStdInitializerList(AdjustedParamType, &X))
+ return false;
+
+ Result = Sema::TDK_Success;
+
+ // Recurse down into the init list.
+ for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+ if ((Result = DeduceTemplateArgumentByListElement(
+ S, TemplateParams, X, ILE->getInit(i), Info, Deduced, TDF)))
+ return true;
+ }
+
+ return true;
+}
+
/// \brief Perform template argument deduction by matching a parameter type
/// against a single expression, where the expression is an element of
/// an initializer list that was originally matched against a parameter
@@ -3204,19 +3238,13 @@ DeduceTemplateArgumentByListElement(Sema &S,
// Handle the case where an init list contains another init list as the
// element.
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
- QualType X;
- if (!S.isStdInitializerList(ParamType.getNonReferenceType(), &X))
+ Sema::TemplateDeductionResult Result;
+ if (!DeduceFromInitializerList(S, TemplateParams,
+ ParamType.getNonReferenceType(), ILE, Info,
+ Deduced, TDF, Result))
return Sema::TDK_Success; // Just ignore this expression.
- // Recurse down into the init list.
- for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
- if (Sema::TemplateDeductionResult Result =
- DeduceTemplateArgumentByListElement(S, TemplateParams, X,
- ILE->getInit(i),
- Info, Deduced, TDF))
- return Result;
- }
- return Sema::TDK_Success;
+ return Result;
}
// For all other cases, just match by type.
@@ -3335,22 +3363,14 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// If the argument is an initializer list ...
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
- // ... then the parameter is an undeduced context, unless the parameter
- // type is (reference to cv) std::initializer_list<P'>, in which case
- // deduction is done for each element of the initializer list, and the
- // result is the deduced type if it's the same for all elements.
- QualType X;
+ TemplateDeductionResult Result;
// Removing references was already done.
- if (!isStdInitializerList(ParamType, &X))
+ if (!DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE,
+ Info, Deduced, TDF, Result))
continue;
- for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
- if (TemplateDeductionResult Result =
- DeduceTemplateArgumentByListElement(*this, TemplateParams, X,
- ILE->getInit(i),
- Info, Deduced, TDF))
- return Result;
- }
+ if (Result)
+ return Result;
// Don't track the argument type, since an initializer list has none.
continue;
}
@@ -3406,19 +3426,15 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// As above, initializer lists need special handling.
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
- QualType X;
- if (!isStdInitializerList(ParamType, &X)) {
+ TemplateDeductionResult Result;
+ if (!DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE,
+ Info, Deduced, TDF, Result)) {
++ArgIdx;
break;
}
- for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
- if (TemplateDeductionResult Result =
- DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X,
- ILE->getInit(i)->getType(),
- Info, Deduced, TDF))
- return Result;
- }
+ if (Result)
+ return Result;
} else {
// Keep track of the argument type and corresponding argument index,
@@ -3952,6 +3968,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
}
QualType Deduced = BuildDecltypeType(Init, Init->getLocStart(), false);
+ if (Deduced.isNull())
+ return DAR_FailedAlreadyDiagnosed;
// FIXME: Support a non-canonical deduced type for 'auto'.
Deduced = Context.getCanonicalType(Deduced);
Result = SubstituteAutoTransform(*this, Deduced).Apply(Type);
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 82ff7c0..7d58017 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1680,11 +1680,24 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
} else if (OldParm->hasUnparsedDefaultArg()) {
NewParm->setUnparsedDefaultArg();
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
- } else if (Expr *Arg = OldParm->getDefaultArg())
- // FIXME: if we non-lazily instantiated non-dependent default args for
- // non-dependent parameter types we could remove a bunch of duplicate
- // conversion warnings for such arguments.
- NewParm->setUninstantiatedDefaultArg(Arg);
+ } else if (Expr *Arg = OldParm->getDefaultArg()) {
+ FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
+ CXXRecordDecl *ClassD = dyn_cast<CXXRecordDecl>(OwningFunc->getDeclContext());
+ if (ClassD && ClassD->isLocalClass() && !ClassD->isLambda()) {
+ // If this is a method of a local class, as per DR1484 its default
+ // arguments must be instantiated.
+ Sema::ContextRAII SavedContext(*this, ClassD);
+ LocalInstantiationScope Local(*this);
+ ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
+ if (NewArg.isUsable())
+ NewParm->setDefaultArg(NewArg.get());
+ } else {
+ // FIXME: if we non-lazily instantiated non-dependent default args for
+ // non-dependent parameter types we could remove a bunch of duplicate
+ // conversion warnings for such arguments.
+ NewParm->setUninstantiatedDefaultArg(Arg);
+ }
+ }
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
@@ -2269,33 +2282,6 @@ bool Sema::InstantiateClassTemplateSpecialization(
// Perform the actual instantiation on the canonical declaration.
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
ClassTemplateSpec->getCanonicalDecl());
-
- // Check whether we have already instantiated or specialized this class
- // template specialization.
- if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared) {
- if (ClassTemplateSpec->getSpecializationKind() ==
- TSK_ExplicitInstantiationDeclaration &&
- TSK == TSK_ExplicitInstantiationDefinition) {
- // An explicit instantiation definition follows an explicit instantiation
- // declaration (C++0x [temp.explicit]p10); go ahead and perform the
- // explicit instantiation.
- ClassTemplateSpec->setSpecializationKind(TSK);
-
- // If this is an explicit instantiation definition, mark the
- // vtable as used.
- if (TSK == TSK_ExplicitInstantiationDefinition &&
- !ClassTemplateSpec->isInvalidDecl())
- MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true);
-
- return false;
- }
-
- // We can only instantiate something that hasn't already been
- // instantiated or specialized. Fail without any diagnostics: our
- // caller will provide an error message.
- return true;
- }
-
if (ClassTemplateSpec->isInvalidDecl())
return true;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f35d1aa..aff2d1c 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2094,14 +2094,13 @@ static void collectUnexpandedParameterPacks(
Sema &S,
TemplateParameterList *Params,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
- for (TemplateParameterList::const_iterator I = Params->begin(),
- E = Params->end(); I != E; ++I) {
- if ((*I)->isTemplateParameterPack())
+ for (const auto &P : *Params) {
+ if (P->isTemplateParameterPack())
continue;
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*I))
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
S.collectUnexpandedParameterPacks(NTTP->getTypeSourceInfo()->getTypeLoc(),
Unexpanded);
- if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(*I))
+ if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
collectUnexpandedParameterPacks(S, TTP->getTemplateParameters(),
Unexpanded);
}
@@ -2731,9 +2730,8 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
typedef SmallVector<NamedDecl *, 8> ParamVector;
ParamVector Params;
Params.reserve(N);
- for (TemplateParameterList::iterator PI = L->begin(), PE = L->end();
- PI != PE; ++PI) {
- NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI));
+ for (auto &P : *L) {
+ NamedDecl *D = cast_or_null<NamedDecl>(Visit(P));
Params.push_back(D);
Invalid = Invalid || !D || D->isInvalidDecl();
}
@@ -3246,10 +3244,18 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// DR1330: In C++11, defer instantiation of a non-trivial
// exception specification.
+ // DR1484: Local classes and their members are instantiated along with the
+ // containing function.
+ bool RequireInstantiation = false;
+ if (CXXRecordDecl *Cls = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext())) {
+ if (Cls->isLocalClass())
+ RequireInstantiation = true;
+ }
if (SemaRef.getLangOpts().CPlusPlus11 &&
EPI.ExceptionSpec.Type != EST_None &&
EPI.ExceptionSpec.Type != EST_DynamicNone &&
- EPI.ExceptionSpec.Type != EST_BasicNoexcept) {
+ EPI.ExceptionSpec.Type != EST_BasicNoexcept &&
+ !RequireInstantiation) {
FunctionDecl *ExceptionSpecTemplate = Tmpl;
if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index d72f259..8d76f69 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2567,19 +2567,19 @@ namespace {
IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) {
switch (nullability) {
case NullabilityKind::NonNull:
- if (!Ident___nonnull)
- Ident___nonnull = PP.getIdentifierInfo("__nonnull");
- return Ident___nonnull;
+ if (!Ident__Nonnull)
+ Ident__Nonnull = PP.getIdentifierInfo("_Nonnull");
+ return Ident__Nonnull;
case NullabilityKind::Nullable:
- if (!Ident___nullable)
- Ident___nullable = PP.getIdentifierInfo("__nullable");
- return Ident___nullable;
+ if (!Ident__Nullable)
+ Ident__Nullable = PP.getIdentifierInfo("_Nullable");
+ return Ident__Nullable;
case NullabilityKind::Unspecified:
- if (!Ident___null_unspecified)
- Ident___null_unspecified = PP.getIdentifierInfo("__null_unspecified");
- return Ident___null_unspecified;
+ if (!Ident__Null_unspecified)
+ Ident__Null_unspecified = PP.getIdentifierInfo("_Null_unspecified");
+ return Ident__Null_unspecified;
}
llvm_unreachable("Unknown nullability kind.");
}
@@ -2900,7 +2900,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
- // Determine whether we should infer __nonnull on pointer types.
+ // Determine whether we should infer _Nonnull on pointer types.
Optional<NullabilityKind> inferNullability;
bool inferNullabilityCS = false;
bool inferNullabilityInnerOnly = false;
@@ -3003,7 +3003,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
case PointerDeclaratorKind::SingleLevelPointer:
- // Infer __nonnull if we are in an assumes-nonnull region.
+ // Infer _Nonnull if we are in an assumes-nonnull region.
if (inAssumeNonNullRegion) {
inferNullability = NullabilityKind::NonNull;
inferNullabilityCS = (context == Declarator::ObjCParameterContext ||
@@ -3013,7 +3013,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case PointerDeclaratorKind::CFErrorRefPointer:
case PointerDeclaratorKind::NSErrorPointerPointer:
- // Within a function or method signature, infer __nullable at both
+ // Within a function or method signature, infer _Nullable at both
// levels.
if (isFunctionOrMethod && inAssumeNonNullRegion)
inferNullability = NullabilityKind::Nullable;
@@ -3023,7 +3023,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (isFunctionOrMethod) {
// On pointer-to-pointer parameters marked cf_returns_retained or
// cf_returns_not_retained, if the outer pointer is explicit then
- // infer the inner pointer as __nullable.
+ // infer the inner pointer as _Nullable.
auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool {
while (NextAttr) {
if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained ||
@@ -3070,7 +3070,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// Local function that checks the nullability for a given pointer declarator.
- // Returns true if __nonnull was inferred.
+ // Returns true if _Nonnull was inferred.
auto inferPointerNullability = [&](SimplePointerKind pointerKind,
SourceLocation pointerLoc,
AttributeList *&attrs) -> AttributeList * {
@@ -5084,8 +5084,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// Duplicated nullability.
if (nullability == *existingNullability) {
Diag(nullabilityLoc, diag::warn_nullability_duplicate)
- << static_cast<unsigned>(nullability)
- << isContextSensitive
+ << DiagNullabilityKind(nullability, isContextSensitive)
<< FixItHint::CreateRemoval(nullabilityLoc);
break;
@@ -5093,10 +5092,8 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// Conflicting nullability.
Diag(nullabilityLoc, diag::err_nullability_conflicting)
- << static_cast<unsigned>(nullability)
- << isContextSensitive
- << static_cast<unsigned>(*existingNullability)
- << false;
+ << DiagNullabilityKind(nullability, isContextSensitive)
+ << DiagNullabilityKind(*existingNullability, false);
return true;
}
@@ -5110,10 +5107,8 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
if (auto existingNullability = desugared->getNullability(Context)) {
if (nullability != *existingNullability) {
Diag(nullabilityLoc, diag::err_nullability_conflicting)
- << static_cast<unsigned>(nullability)
- << isContextSensitive
- << static_cast<unsigned>(*existingNullability)
- << false;
+ << DiagNullabilityKind(nullability, isContextSensitive)
+ << DiagNullabilityKind(*existingNullability, false);
// Try to find the typedef with the existing nullability specifier.
if (auto typedefType = desugared->getAs<TypedefType>()) {
@@ -5123,7 +5118,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
= AttributedType::stripOuterNullability(underlyingType)) {
if (*typedefNullability == *existingNullability) {
Diag(typedefDecl->getLocation(), diag::note_nullability_here)
- << static_cast<unsigned>(*existingNullability);
+ << DiagNullabilityKind(*existingNullability, false);
}
}
}
@@ -5135,7 +5130,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// If this definitely isn't a pointer type, reject the specifier.
if (!desugared->canHaveNullability()) {
Diag(nullabilityLoc, diag::err_nullability_nonpointer)
- << static_cast<unsigned>(nullability) << isContextSensitive << type;
+ << DiagNullabilityKind(nullability, isContextSensitive) << type;
return true;
}
@@ -5148,10 +5143,10 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
pointeeType->isObjCObjectPointerType() ||
pointeeType->isMemberPointerType()) {
Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
- << static_cast<unsigned>(nullability)
+ << DiagNullabilityKind(nullability, true)
<< type;
Diag(nullabilityLoc, diag::note_nullability_type_specifier)
- << static_cast<unsigned>(nullability)
+ << DiagNullabilityKind(nullability, false)
<< type
<< FixItHint::CreateReplacement(nullabilityLoc,
getNullabilitySpelling(nullability));
@@ -5202,16 +5197,24 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
// Complain about the nullability qualifier being in the wrong
// place.
- unsigned pointerKind
- = chunk.Kind == DeclaratorChunk::Pointer ? (inFunction ? 3 : 0)
- : chunk.Kind == DeclaratorChunk::BlockPointer ? 1
- : inFunction? 4 : 2;
+ enum {
+ PK_Pointer,
+ PK_BlockPointer,
+ PK_MemberPointer,
+ PK_FunctionPointer,
+ PK_MemberFunctionPointer,
+ } pointerKind
+ = chunk.Kind == DeclaratorChunk::Pointer ? (inFunction ? PK_FunctionPointer
+ : PK_Pointer)
+ : chunk.Kind == DeclaratorChunk::BlockPointer ? PK_BlockPointer
+ : inFunction? PK_MemberFunctionPointer : PK_MemberPointer;
auto diag = state.getSema().Diag(attr.getLoc(),
diag::warn_nullability_declspec)
- << static_cast<unsigned>(mapNullabilityAttrKind(attr.getKind()))
+ << DiagNullabilityKind(mapNullabilityAttrKind(attr.getKind()),
+ attr.isContextSensitiveKeywordAttribute())
<< type
- << pointerKind;
+ << static_cast<unsigned>(pointerKind);
// FIXME: MemberPointer chunks don't carry the location of the *.
if (chunk.Kind != DeclaratorChunk::MemberPointer) {
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 73dde7c..80896be 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1321,11 +1321,12 @@ public:
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildOMPExecutableDirective(OpenMPDirectiveKind Kind,
DeclarationNameInfo DirName,
+ OpenMPDirectiveKind CancelRegion,
ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
- return getSema().ActOnOpenMPExecutableDirective(Kind, DirName, Clauses,
- AStmt, StartLoc, EndLoc);
+ return getSema().ActOnOpenMPExecutableDirective(
+ Kind, DirName, CancelRegion, Clauses, AStmt, StartLoc, EndLoc);
}
/// \brief Build a new OpenMP 'if' clause.
@@ -1551,6 +1552,19 @@ public:
EndLoc);
}
+ /// \brief Build a new OpenMP 'depend' pseudo clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *
+ RebuildOMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList,
+ StartLoc, LParenLoc, EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -5392,7 +5406,7 @@ QualType TreeTransform<Derived>::TransformAttributedType(
if (auto nullability = oldType->getImmediateNullability()) {
if (!modifiedType->canHaveNullability()) {
SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer)
- << static_cast<unsigned>(*nullability) << false << modifiedType;
+ << DiagNullabilityKind(*nullability, false) << modifiedType;
return QualType();
}
}
@@ -6664,7 +6678,9 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
I != E; ++I) {
if (*I) {
+ getDerived().getSema().StartOpenMPClause((*I)->getClauseKind());
OMPClause *Clause = getDerived().TransformOMPClause(*I);
+ getDerived().getSema().EndOpenMPClause();
if (Clause)
TClauses.push_back(Clause);
} else {
@@ -6700,10 +6716,16 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
DirName = cast<OMPCriticalDirective>(D)->getDirectiveName();
DirName = getDerived().TransformDeclarationNameInfo(DirName);
}
+ OpenMPDirectiveKind CancelRegion = OMPD_unknown;
+ if (D->getDirectiveKind() == OMPD_cancellation_point) {
+ CancelRegion = cast<OMPCancellationPointDirective>(D)->getCancelRegion();
+ } else if (D->getDirectiveKind() == OMPD_cancel) {
+ CancelRegion = cast<OMPCancelDirective>(D)->getCancelRegion();
+ }
return getDerived().RebuildOMPExecutableDirective(
- D->getDirectiveKind(), DirName, TClauses, AssociatedStmt.get(),
- D->getLocStart(), D->getLocEnd());
+ D->getDirectiveKind(), DirName, CancelRegion, TClauses,
+ AssociatedStmt.get(), D->getLocStart(), D->getLocEnd());
}
template <typename Derived>
@@ -6947,6 +6969,28 @@ TreeTransform<Derived>::TransformOMPTeamsDirective(OMPTeamsDirective *D) {
return Res;
}
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPCancellationPointDirective(
+ OMPCancellationPointDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_cancellation_point, DirName,
+ nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPCancelDirective(OMPCancelDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_cancel, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
@@ -7253,6 +7297,22 @@ OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) {
C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPDependClause(
+ C->getDependencyKind(), C->getDependencyLoc(), C->getColonLoc(), Vars,
+ C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
@@ -9368,7 +9428,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
}
// Capture the transformed variable.
- getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind);
+ getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind,
+ EllipsisLoc);
}
if (!FinishedExplicitCaptures)
getSema().finishLambdaExplicitCaptures(LSI);
OpenPOWER on IntegriCloud