diff options
author | dim <dim@FreeBSD.org> | 2015-07-05 14:23:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-07-05 14:23:59 +0000 |
commit | e7bcad327814a78ecb8d5f5545d2e3df84c67a5c (patch) | |
tree | ac719b5984165053bf83d71142e4d96b609b9784 /lib/Sema | |
parent | 9dd834653b811ad20382e98a87dff824980c9916 (diff) | |
download | FreeBSD-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.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/JumpDiagnostics.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 73 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 111 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 40 | ||||
-rw-r--r-- | lib/Sema/SemaExceptionSpec.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 32 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 127 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaOpenMP.cpp | 297 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 84 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 50 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 71 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 73 |
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); |